Author Topic: Repurpose a Single Use Libero CB temperature logger  (Read 2921 times)

0 Members and 1 Guest are viewing this topic.

Offline monthlybasilTopic starter

  • Newbie
  • Posts: 8
  • Country: au
Repurpose a Single Use Libero CB temperature logger
« on: September 30, 2022, 12:51:42 am »
I have a single use temperature logger, that is apparently useless when it has been received at the delivery location and read by plugging it in.

Not happy at this piece having no further use, I wanted to see if there is another purpose for this. So I opened it up and removed the battery to try and reset it. No dice. It still displayed Stop.

I tried holding the start stop button while inserting the battery and bLdr is displayed. Plugging it in now, instead of showing the compiled PDF, shows an empty folder.

I'm assuming that, provided a new firmware file at this stage, the temperature logger could be customised and then used to check if the fridge has stopped running while on holidays, log min and max temps, and maybe something awesome that I haven't thought of yet.

I'm out of my depth and need the next step.

Any ideas or assistance is appreciated.





 

Offline eutectique

  • Frequent Contributor
  • **
  • Posts: 386
  • Country: be
Re: Repurpose a Single Use Libero CB temperature logger
« Reply #1 on: September 30, 2022, 04:50:08 am »
Quote
Plugging it in now, instead of showing the compiled PDF, shows an empty folder.

Can you create an empty pdf file there?
 
The following users thanked this post: Fraser, monthlybasil

Offline monthlybasilTopic starter

  • Newbie
  • Posts: 8
  • Country: au
Re: Repurpose a Single Use Libero CB temperature logger
« Reply #2 on: September 30, 2022, 05:27:48 am »
I didn't want to try anything just yet, I'm assuming bLdr is shorthand for bootloader, so either that's when it can be programmed, either with a .bin or a suitable piece of software.

But I suppose if I can get it to bootloader I can do pretty much anything, because I can get it back to this point and try again?

I was going to try a 'blink' firmware, that flashes each segment on the LCD one by one.

Is this arduino ide level? Or do I need to make it in platformIO or something else? I've not messed with these ICs before.
 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12852
Re: Repurpose a Single Use Libero CB temperature logger
« Reply #3 on: September 30, 2022, 05:34:17 am »
I agree 'bLdr' probably stands for boot-loader, i.e. its expecting new firmware.  It may be looking for a firmware file to be written to the mass storage device it presents as, possibly encrypted and/or in a proprietary format, or it may expect it over some other interface, connected via pogo pins to the test pads on the underside of the PCB.

If you study the datasheet of the STM32L073CZT6 MCU, and do a bit of research you can probably figure out how to wipe the chip and get it into a more standard bootloader mode so you can use your own firmware.  If you haven't done STM32 development previously you've got a long steep road ahead of you!  It certainly isn't going to be as easy as adding a new board to the Arduino IDE, as there don't seem to be any using that specific MCU.
 
The following users thanked this post: monthlybasil

Offline voltsandjolts

  • Supporter
  • ****
  • Posts: 2299
  • Country: gb
Re: Repurpose a Single Use Libero CB temperature logger
« Reply #4 on: September 30, 2022, 09:46:41 am »
There's a chance that the oem firmware displays 'bLdr' and then jumps to the built-in STM32 usb dfu bootloader.
Might be worth trying stm32 dFuSe.
 
The following users thanked this post: monthlybasil

Offline eutectique

  • Frequent Contributor
  • **
  • Posts: 386
  • Country: be
Re: Repurpose a Single Use Libero CB temperature logger
« Reply #5 on: September 30, 2022, 10:37:46 am »
Is this arduino ide level? Or do I need to make it in platformIO or something else? I've not messed with these ICs before.

If you followed Microcontrollers section for a couple of past days, you've probably noticed three discussions dedicated to tools:

https://www.eevblog.com/forum/microcontrollers/lets-discuss-telluriums-tutorial/
https://www.eevblog.com/forum/microcontrollers/rant-why-i-dumped-platform-io-ide-after-a-week/
https://www.eevblog.com/forum/microcontrollers/is-st-cube-ide-a-piece-of-buggy-crap/
« Last Edit: September 30, 2022, 12:47:03 pm by eutectique »
 
The following users thanked this post: monthlybasil

Offline ozcar

  • Frequent Contributor
  • **
  • Posts: 322
  • Country: au
Re: Repurpose a Single Use Libero CB temperature logger
« Reply #6 on: September 30, 2022, 08:03:11 pm »
If you study the datasheet of the STM32L073CZT6 MCU, and do a bit of research you can probably figure out how to wipe the chip and get it into a more standard bootloader mode so you can use your own firmware.  If you haven't done STM32 development previously you've got a long steep road ahead of you!  It certainly isn't going to be as easy as adding a new board to the Arduino IDE, as there don't seem to be any using that specific MCU.

The "official STM32DUINO" core does include an entry for "Generic L073CZYx" - should be "close enough".
 
The following users thanked this post: Ian.M, monthlybasil

Offline monthlybasilTopic starter

  • Newbie
  • Posts: 8
  • Country: au
Re: Repurpose a Single Use Libero CB temperature logger
« Reply #7 on: October 02, 2022, 05:15:39 am »
Here's what I have so far.

I'm not 100% sure on the battery level or the temperature probe sensing circuits, but the LCD segments I'm confident with.



   LCD Segments
   x      x      x      COM3   COM2   COM1   COM0   x      x      x
   SEG0   SEG1   SEG5   SEG6   SEG10   SEG11   SEG12   SEG13   SEG14   SEG15
   
   PA3   temp_sense_enable?   Set high to power the NTC?
   PA5   temp_sense?         Temp read ADC on this pin
   PH0   button?         
   PH1   batt level?         Sense battery level?

   PC14 RCC   Ceramic Clock
   PC15 RCC   Ceramic Clock
 

Offline voltsandjolts

  • Supporter
  • ****
  • Posts: 2299
  • Country: gb
Re: Repurpose a Single Use Libero CB temperature logger
« Reply #8 on: October 02, 2022, 08:55:58 am »
Manufacturer datasheet for this temperature logger is here.
Product line web page is here.

Do you have an example of the PDF produced by this logger?
I'm just interested to see how the PDF is created by this mcu.
« Last Edit: October 02, 2022, 09:08:57 am by voltsandjolts »
 

Offline monthlybasilTopic starter

  • Newbie
  • Posts: 8
  • Country: au
Re: Repurpose a Single Use Libero CB temperature logger
« Reply #9 on: October 02, 2022, 11:45:25 am »
So I am able to short the boot pin and I think I can upload new firmware to it.

next challenge is how to cycle through the multiplexed lcd elements to identify the lcd pinouts.

I have thought about driving them as GPIO pins, but I need to apply ac to them. So probably the best bet is to write something in STM32CubeIDE but I dont know how to initialise the LCD.

this video was helpful with the methodology to determine the pinouts

eating this elephant one bite at a time.

 

Offline voltsandjolts

  • Supporter
  • ****
  • Posts: 2299
  • Country: gb
Re: Repurpose a Single Use Libero CB temperature logger
« Reply #10 on: October 02, 2022, 12:47:35 pm »
Thanks for the info.

I can upload new firmware to it.

What PC software are you using, STM32 DfuSe?
 

Offline monthlybasilTopic starter

  • Newbie
  • Posts: 8
  • Country: au
Re: Repurpose a Single Use Libero CB temperature logger
« Reply #11 on: October 05, 2022, 11:14:16 am »
So I've been researching (https://st-onlinetraining.s3.amazonaws.com/STM32L4_Peripheral_Liquid_Crystal_Display_interface_(LCD)/index.html) and messing around, and I cant get anything to display on the LCD. would the code below produce anything, assuming the other voltages and clk settings are suitable?

Code: [Select]
/* USER CODE BEGIN WHILE */
  while (1)
  {
HAL_LCD_Clear(&hlcd);
HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER0, 0x0000, 32);
HAL_LCD_UpdateDisplayRequest(&hlcd); HAL_Delay(500);
HAL_LCD_Clear(&hlcd);
HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER1, 0x0000, 32);
HAL_LCD_UpdateDisplayRequest(&hlcd); HAL_Delay(500);
HAL_LCD_Clear(&hlcd);
HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER2, 0x0000, 32);
HAL_LCD_UpdateDisplayRequest(&hlcd); HAL_Delay(500);
HAL_LCD_Clear(&hlcd);
HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER3, 0x0000, 32);
HAL_LCD_UpdateDisplayRequest(&hlcd); HAL_Delay(500);
HAL_LCD_Clear(&hlcd);
HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER4, 0x0000, 32);
HAL_LCD_UpdateDisplayRequest(&hlcd); HAL_Delay(500);
HAL_LCD_Clear(&hlcd);
HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER5, 0x0000, 32);
HAL_LCD_UpdateDisplayRequest(&hlcd); HAL_Delay(500);
HAL_LCD_Clear(&hlcd);
HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER6, 0x0000, 32);
HAL_LCD_UpdateDisplayRequest(&hlcd); HAL_Delay(500);
HAL_LCD_Clear(&hlcd);
HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER7, 0x0000, 32);
HAL_LCD_UpdateDisplayRequest(&hlcd); HAL_Delay(500);

    /* USER CODE END WHILE */

 

Offline monthlybasilTopic starter

  • Newbie
  • Posts: 8
  • Country: au
Re: Repurpose a Single Use Libero CB temperature logger
« Reply #12 on: October 07, 2022, 07:54:16 am »
So LCD is working

Needed to set the LCD Contrast Control to 2.68V.

The following illuminates all the segments

Code: [Select]
  while (1)
  {
  uint16_t screendata1 = 0b1111110001100011;
  uint16_t screendata2 = 0b1111110001100011;
  uint16_t screendata3 = 0b1111110001100011;
  uint16_t screendata4 = 0b1111110001000011;

      HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER0, 0xFC63, screendata1);
      HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER2, 0xFC63, screendata2);
      HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER4, 0xFC63, screendata3);
      HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER6, 0xFC43, screendata4);
      HAL_LCD_UpdateDisplayRequest(&hlcd);
      HAL_Delay(1000);
      HAL_LCD_Clear(&hlcd);
      HAL_Delay(1000);
     
    /* USER CODE END WHILE */

And the segments are mapped out as:

Code: [Select]
RAM REG 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
0 LowBatt 4b 4a 3b 3a 2b 2a 1b 1a RUN
2 Profile 4g 4f 3g 3f 2g 2f 1g 1f CROSS
4 degC 4c 4e 3c 3e 2c 2e 1c 1e TICK
6 degF % 4d dp3 3d dp2 2d 1d DIAG

now to mess with ADC to get a temp readout over serial.
« Last Edit: October 07, 2022, 11:20:04 pm by monthlybasil »
 

Offline monthlybasilTopic starter

  • Newbie
  • Posts: 8
  • Country: au
Re: Repurpose a Single Use Libero CB temperature logger
« Reply #13 on: October 10, 2022, 11:42:00 am »
Can anyone help me with changing the LCD Segment Pins so they are in order, or manipulate the order of them so I dont have two 3 bit gaps in the pin table? I have not had much luck with googling a solution.
 

Online DavidAlfa

  • Super Contributor
  • ***
  • Posts: 5895
  • Country: es
Re: Repurpose a Single Use Libero CB temperature logger
« Reply #14 on: October 12, 2022, 02:18:17 am »
I'd use a combination of indexing tables and functions, using different functions for symbols (lowbatt, etc), which only need to modify one bit of a single register, and the alphanuneric segments, where all memory registers need to be modified to construct the final character.
That way you step to high level functions, making the access much easier.

This is enough as an initial test, untested, written using the phone  :P

Code: [Select]
#include <stdbool.h>
#include <stdint.h>

#define icon_count 9
#define ON true
#define OFF false

typedef enum {
    icon_lowbatt = 0,
    icon_run,
    icon_profile,
    icon_cross,
    icon_degC,
    icon_tick,
    icon_degF,
    icon_percent,
    icon_diag,
} icon_name_t;

typedef struct{
    const uint8_t reg;
    const uint8_t mask;
} icon_data_t;

icon_data_t icon_data[icon_count] = {
    [icon_lowbatt] = { LCD_RAM_REGISTER0, 15 },
    [icon_run]     = { LCD_RAM_REGISTER0, 0  },
    [icon_profile] = { LCD_RAM_REGISTER2, 15 },
    [icon_cross]   = { LCD_RAM_REGISTER2, 0  },
    [icon_degC]    = { LCD_RAM_REGISTER4, 15 },
    [icon_tick]    = { LCD_RAM_REGISTER4, 0  },
    [icon_degF]    = { LCD_RAM_REGISTER6, 15 },
    [icon_percent] = { LCD_RAM_REGISTER6, 14 },
    [icon_diag]    = { LCD_RAM_REGISTER6, 0  },
};


void set_icon(icon_name_t i, bool enable){
    uint16_t mask = 1 << icon_data[i].mask;
    HAL_LCD_Write(&hlcd, icon_data[i].reg, mask, ( enable ? mask : 0 ) );
    HAL_LCD_UpdateDisplayRequest(&hlcd);
}

void main(void){
    while(1){
        set_icon(icon_run, ON);
        HAL_Delay(1000);
        set_icon(icon_run, OFF);
        HAL_Delay(1000);
    }
}
« Last Edit: October 13, 2022, 07:30:49 pm by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 
The following users thanked this post: monthlybasil

Online DavidAlfa

  • Super Contributor
  • ***
  • Posts: 5895
  • Country: es
Re: Repurpose a Single Use Libero CB temperature logger
« Reply #15 on: October 12, 2022, 03:59:36 am »
Digits test. Probably could be simplified, but it lets you see the mechanics very easily.
Code: [Select]
#include <stdbool.h>
#include <stdint.h>

#define char_count 4
#define seg_count 8

#define A   1
#define B   2
#define C   4
#define D   8
#define E   16
#define F   32
#define G   64

const uint8_t digits[] = {
    (A+B+C+D+E+F),         //0
    (B+C),                 //1
    (A+B+G+E+D),           //2
    (A+B+C+D+G),           //3
    (F+G+B+C),             //4
    (A+F+G+C+D),           //5
    (A+F+E+D+C+G),         //6
    (A+B+C),               //7
    (A+B+C+D+E+F+G),       //8
    (D+C+B+A+F+G),         //9
};

typedef enum {
    seg_a = 0,
    seg_b,
    seg_c,
    seg_d,
    seg_e,
    seg_f,
    seg_g,
    seg_dp,
} seg_name_t;

typedef enum {
    char_1 = 0,
    char_2,
    char_3,
    char_4,
} char_name_t;

typedef struct{
    const uint8_t reg;
    const uint8_t mask;
} seg_data_t;

seg_data_t seg_data[char_count][seg_count] = {
    [char_1] = {
         [seg_a]   = { LCD_RAM_REGISTER0, 1  },
         [seg_b]   = { LCD_RAM_REGISTER0, 5  },
         [seg_c]   = { LCD_RAM_REGISTER4, 5  },
         [seg_d]   = { LCD_RAM_REGISTER6, 1  },
         [seg_e]   = { LCD_RAM_REGISTER4, 1  },
         [seg_f]   = { LCD_RAM_REGISTER2, 1  },
         [seg_g]   = { LCD_RAM_REGISTER2, 5  },
    },
    [char_2] = {
         [seg_a]   = { LCD_RAM_REGISTER0, 6  },
         [seg_b]   = { LCD_RAM_REGISTER0, 10 },
         [seg_c]   = { LCD_RAM_REGISTER4, 10 },
         [seg_d]   = { LCD_RAM_REGISTER6, 6  },
         [seg_e]   = { LCD_RAM_REGISTER4, 6  },
         [seg_f]   = { LCD_RAM_REGISTER2, 6  },
         [seg_g]   = { LCD_RAM_REGISTER2, 10 },
         [seg_dp]  = { LCD_RAM_REGISTER6, 10 },
    },
    [char_3] = {
         [seg_a]   = { LCD_RAM_REGISTER0, 11 },
         [seg_b]   = { LCD_RAM_REGISTER0, 12 },
         [seg_c]   = { LCD_RAM_REGISTER4, 12 },
         [seg_d]   = { LCD_RAM_REGISTER6, 11 },
         [seg_e]   = { LCD_RAM_REGISTER4, 11 },
         [seg_f]   = { LCD_RAM_REGISTER2, 11 },
         [seg_g]   = { LCD_RAM_REGISTER2, 12 },
         [seg_dp]  = { LCD_RAM_REGISTER6, 12 },
    },
    [char_4] = {
         [seg_a]   = { LCD_RAM_REGISTER0, 13 },
         [seg_b]   = { LCD_RAM_REGISTER0, 14 },
         [seg_c]   = { LCD_RAM_REGISTER4, 14 },
         [seg_d]   = { LCD_RAM_REGISTER6, 13 },
         [seg_e]   = { LCD_RAM_REGISTER4, 13 },
         [seg_f]   = { LCD_RAM_REGISTER2, 13 },
         [seg_g]   = { LCD_RAM_REGISTER2, 14 },
    },
};

void clear_char(char_name_t c){
    uint16_t mask;

    for(uint8_t i=0; i<seg_count; i++){
        mask = 1 << seg_data[c][i].mask;
        HAL_LCD_Write(&hlcd, seg_data[c][i].reg, mask, 0 );
    }
    HAL_LCD_UpdateDisplayRequest(&hlcd);
}

// Dp not implemented
void write_char(char_name_t c, uint8_t number, bool dp){
    uint16_t mask;

    if (number>9)
        number=8;
       
    for(uint8_t i=0; i<seg_count; i++){
        mask = 1 << seg_data[c][i].mask;
        HAL_LCD_Write(&hlcd, seg_data[c][i].reg, mask,
        ( ((1<<i) & digits[number]) ? mask : 0 ) );
    }
    HAL_LCD_UpdateDisplayRequest(&hlcd);
}

void main(void){
    uint8_t a=0, b=0, c=0, d=0;

    while(1){
        write_char(char_1, a, false);
        write_char(char_2, b, false);
        write_char(char_3, c, false);
        write_char(char_4, d, false);
 
        if(++a>9){
            a=0;
            if(++b>9){
                b=0;
                if(++c>9){
                    c=0;
                    if(++d>9)
                        d=0;
                }
            }
        }
        HAL_Delay(1000);
    }
}
« Last Edit: October 13, 2022, 07:36:07 pm by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 
The following users thanked this post: monthlybasil

Offline monthlybasilTopic starter

  • Newbie
  • Posts: 8
  • Country: au
Re: Repurpose a Single Use Libero CB temperature logger
« Reply #16 on: March 12, 2024, 09:16:55 am »
I know its been a while, but I wanted to put this here for others to use, and maybe get some feedback.

this is my first try at writing anything in c, I'm very much a beginner, that's probably why it's taken so long.

anyway, here's main.c from my project.

It might look janky, but it works. and other than some calibration I'll need to do when I'm home with a multimeter, it reports temps.

Code: [Select]
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usb_device.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "usbd_cdc_if.h"
#include <math.h>
#include <stdbool.h>
#include <stdint.h>

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
// Steinhart-Hart coefficients
#define A_COEFF 0.001125308852122
#define B_COEFF 0.000234711863267
#define C_COEFF 8.76711446883e-08
#define REFERENCE_RESISTANCE 20000.0 // 20 kΩ used for the temperature calculation

// Define the number of characters and segments
#define char_count 4
#define seg_count 7

// Define enumerations for segment and character names
typedef enum {
seg_a = 0,
seg_b,
seg_c,
seg_d,
seg_e,
seg_f,
seg_g,
} seg_name_t;

typedef enum {
char_1 = 0,
char_2,
char_3,
char_4,
} char_name_t;

// 2D array to hold segment data for each character
typedef struct {
const uint8_t reg;   // LCD RAM register to write data to
const uint16_t mask;  // Bit mask for the specific segment within the register
} seg_data_t;

seg_data_t seg_data[char_count][seg_count] = {
[char_1] = {
[seg_a]  = { LCD_RAM_REGISTER0, 13 }, //0
[seg_b]  = { LCD_RAM_REGISTER0, 14 }, //1
[seg_c]  = { LCD_RAM_REGISTER4, 14 }, //2
[seg_d]  = { LCD_RAM_REGISTER6, 13 }, //3
[seg_e]  = { LCD_RAM_REGISTER4, 13 }, //4
[seg_f]  = { LCD_RAM_REGISTER2, 13 }, //5
[seg_g]  = { LCD_RAM_REGISTER2, 14 }, //6
},
[char_2] = {
[seg_a]  = { LCD_RAM_REGISTER0, 11 },
[seg_b]  = { LCD_RAM_REGISTER0, 12 },
[seg_c]  = { LCD_RAM_REGISTER4, 12 },
[seg_d]  = { LCD_RAM_REGISTER6, 11 },
[seg_e]  = { LCD_RAM_REGISTER4, 11 },
[seg_f]  = { LCD_RAM_REGISTER2, 11 },
[seg_g]  = { LCD_RAM_REGISTER2, 12 },
},
[char_3] = {
[seg_a]  = { LCD_RAM_REGISTER0, 6  },
[seg_b]  = { LCD_RAM_REGISTER0, 10 },
[seg_c]  = { LCD_RAM_REGISTER4, 10 },
[seg_d]  = { LCD_RAM_REGISTER6, 6  },
[seg_e]  = { LCD_RAM_REGISTER4, 6  },
[seg_f]  = { LCD_RAM_REGISTER2, 6  },
[seg_g]  = { LCD_RAM_REGISTER2, 10 },
},
[char_4] = {
[seg_a]  = { LCD_RAM_REGISTER0, 1  },
[seg_b]  = { LCD_RAM_REGISTER0, 5  },
[seg_c]  = { LCD_RAM_REGISTER4, 5  },
[seg_d]  = { LCD_RAM_REGISTER6, 1  },
[seg_e]  = { LCD_RAM_REGISTER4, 1  },
[seg_f]  = { LCD_RAM_REGISTER2, 1  },
[seg_g]  = { LCD_RAM_REGISTER2, 5  },
},
};

const uint8_t SevenSegmentASCII[128] = {
0b00000000, /*   0 - */
0b00000000, /*   1 - */
0b00000000, /*   2 - */
0b00000000, /*   3 - */
0b00000000, /*   4 - */
0b00000000, /* 5 - */
0b00000000, /* 6 - */
0b00000000, /* 7 - */
0b00000000, /* 8 - */
0b00000000, /*   9 - */
0b00000000, /*  10 - */
0b00000000, /*  11 - */
0b00000000, /*  12 - */
0b00000000, /*  13 - */
0b00000000, /*  14 - */
0b00000000, /*  15 - */
0b00000000, /*  16 - */
0b00000000, /*  17 - */
0b00000000, /*  18 - */
0b00000000, /*  19 - */
0b00000000, /*  20 - */
0b00000000, /*  21 - */
0b00000000, /*  22 - */
0b00000000, /*  23 - */
0b00000000, /*  24 - */
0b00000000, /*  25 - */
0b00000000, /*  26 - */
0b00000000, /*  27 - */
0b00000000, /*  28 - */
0b00000000, /*  29 - */
0b00000000, /*  30 - */
0b00000000, /*  31 - */
0b00000000, /*  32 - space */
0b10000110, /*  33 - ! */
0b00100010, /*  34 - " */
0b01111110, /*  35 - # */
0b01101101, /*  36 - $ */
0b11010010, /*  37 - % */
0b01000110, /*  38 - & */
0b00100000, /*  39 - ' */
0b00101001, /*  40 - ( */
0b00001011, /*  41 - ) */
0b00100001, /*  42 - * */
0b01110000, /*  43 - + */
0b00010000, /*  44 - , */
0b01000000, /*  45 - - */
0b10000000, /*  46 - . */
0b01010010, /*  47 - / */
0b00111111, /*  48 - 0 */
0b00000110, /*  49 - 1 */
0b01011011, /*  50 - 2 */
0b01001111, /*  51 - 3 */
0b01100110, /*  52 - 4 */
0b01101101, /*  53 - 5 */
0b01111101, /*  54 - 6 */
0b00000111, /*  55 - 7 */
0b01111111, /*  56 - 8 */
0b01101111, /*  57 - 9 */
0b00001001, /*  58 - : */
0b00001101, /*  59 - ; */
0b01100001, /*  60 - < */
0b01001000, /*  61 - = */
0b01000011, /*  62 - > */
0b11010011, /*  63 - ? */
0b01011111, /*  64 - @ */
0b01110111, /*  65 - A */
0b01111100, /*  66 - B */
0b00111001, /*  67 - C */
0b01011110, /*  68 - D */
0b01111001, /*  69 - E */
0b01110001, /*  70 - F */
0b00111101, /*  71 - G */
0b01110110, /*  72 - H */
0b00110000, /*  73 - I */
0b00011110, /*  74 - J */
0b01110101, /*  75 - K */
0b00111000, /*  76 - L */
0b00010101, /*  77 - M */
0b00110111, /*  78 - N */
0b00111111, /*  79 - O */
0b01110011, /*  80 - P */
0b01101011, /*  81 - Q */
0b00110011, /*  82 - R */
0b01101101, /*  83 - S */
0b01111000, /*  84 - T */
0b00111110, /*  85 - U */
0b00111110, /*  86 - V */
0b00101010, /*  87 - W */
0b01110110, /*  88 - X */
0b01101110, /*  89 - Y */
0b01011011, /*  90 - Z */
0b00111001, /*  91 - [ */
0b01100100, /*  92 - \ */
0b00001111, /*  93 - ] */
0b00100011, /*  94 - ^ */
0b00001000, /*  95 - _ */
0b00000010, /*  96 - ` */
0b01011111, /*  97 - a */
0b01111100, /*  98 - b */
0b01011000, /*  99 - c */
0b01011110, /* 100 - d */
0b01111011, /* 101 - e */
0b01110001, /* 102 - f */
0b01101111, /* 103 - g */
0b01110100, /* 104 - h */
0b00010000, /* 105 - i */
0b00001100, /* 106 - j */
0b01110101, /* 107 - k */
0b00110000, /* 108 - l */
0b00010100, /* 109 - m */
0b01010100, /* 110 - n */
0b01011100, /* 111 - o */
0b01110011, /* 112 - p */
0b01100111, /* 113 - q */
0b01010000, /* 114 - r */
0b01101101, /* 115 - s */
0b01111000, /* 116 - t */
0b00011100, /* 117 - u */
0b00011100, /* 118 - v */
0b00010100, /* 119 - w */
0b01110110, /* 120 - x */
0b01101110, /* 121 - y */
0b01011011, /* 122 - z */
0b01000110, /* 123 - { */
0b00110000, /* 124 - | */
0b01110000, /* 125 - } */
0b00000001, /* 126 - ~ */
0b11111111, /* 127 - del */
};

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
ADC_HandleTypeDef hadc;
LCD_HandleTypeDef hlcd;
RTC_HandleTypeDef hrtc;

/* USER CODE BEGIN PV */

uint32_t adc_value;

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_LCD_Init(void);
static void MX_ADC_Init(void);
static void MX_RTC_Init(void);
/* USER CODE BEGIN PFP */

// Main function

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_LCD_Init();
  MX_ADC_Init();
  MX_RTC_Init();
  MX_USB_DEVICE_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
while (1) {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

void init_display(){

//All segments display test
/* RAM REG 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 A
0 LowBatt 1b 1a 2b 2a 3b 3a 4b 4a RUN F B
2 Profile 1g 1f 2g 2f 3g 3f 4g 4f CROSS G
4 degC 1c 1e 2c 2e 3c 3e 4c 4e TICK E C
6 degF % 1d 2dp 2d 3dp 3d 4d DIAG D dp

  1111110000000000
  5432109876543210 */
HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER0, 0xFC63, 0b1111110001100011);
HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER2, 0xFC63, 0b1111110001100011);
HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER4, 0xFC63, 0b1111110001100011);
HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER6, 0xFC63, 0b0111110001000011);
HAL_LCD_UpdateDisplayRequest(&hlcd);
HAL_Delay(1000);
HAL_LCD_Clear(&hlcd);
HAL_Delay(100);
}

void init_sensors(){
//show 'Init' on display
HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER0, 0xFC63, 0x20);
HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER2, 0xFC63, 0x6400);
HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER4, 0xFC63, 0x3460);
HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER6, 0xFC43, 0x2000);
HAL_LCD_UpdateDisplayRequest(&hlcd);
//instead of Delay below, change this to calibrate the temp sensor, maybe also show the battery percentage?
HAL_Delay(5000);
HAL_LCD_Clear(&hlcd);
}

void DisplayNumber(float number, int unit){ //units not implemented yet
// TODO UNITS using LCD symbols, input sanistisation?

// Round the number to the desired decimal places
    int decimalPlaces = 0;

if (number < -999.5){
number = -999;
decimalPlaces = 0;}
else if (-999.5 < number && number < -99.95){
decimalPlaces = 0;}
else if (-99.95 < number && number < -9.95){
decimalPlaces = 1;}
else if (-9.95 < number && number < 99.95){
decimalPlaces = 2;}
else if (99.95 < number && number < 999.95){
decimalPlaces = 1;}
else if (999.95 < number && number < 9999.5){
decimalPlaces = 0;}
else if (number > 9999.5){
number = 9999;
decimalPlaces = 0;}
else {number = 0;
decimalPlaces = 2;}

double roundedNumber = number * pow(10, decimalPlaces);
roundedNumber = round(roundedNumber);
double unroundedNumber = roundedNumber / pow(10, decimalPlaces);

HAL_LCD_Clear(&hlcd);

if (decimalPlaces == 2){
HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER6, 1 << 10, 1 << 10);

}
else if (decimalPlaces == 1){
HAL_LCD_Write(&hlcd, LCD_RAM_REGISTER6, 1 << 12, 1 << 12);
}
else;// (no decimal places)

for(int c=0; c < char_count; c++){ //For each Character:
int digit = (abs((int)(roundedNumber / pow(10, c)))) % 10; // Extract digit at position c

//char buffer[100]; // communicate on the USB serial as each digit is written
//int len = sprintf(buffer, "number: %f Input: %4.2f, dp: %d char %d, number: %d, ASCII: 0x%2X\r\n", number, unroundedNumber, decimalPlaces, c, digit, SevenSegmentASCII[digit + 48]);
//CDC_Transmit_FS((uint8_t *)buffer, len);
for(uint8_t s=0; s<seg_count; s++){ //each segment gets written
int bit = ((SevenSegmentASCII[digit + 48] >> s) & 1); //bitshift to the 's' segment and check if its a 1, (by ANDing segment with 1)

if (c == 3 && unroundedNumber < 0){ //is negative
bit = ((SevenSegmentASCII[45] >> s) & 1);
}
else if (c == 3 && 0 <= unroundedNumber && unroundedNumber < 10){//between 0 and 10
bit = ((SevenSegmentASCII[32] >> s) & 1);
}

HAL_LCD_Write(&hlcd, seg_data[c][s].reg, 0xFC63, bit << seg_data[c][s].mask); //unmask all bits, and write that segments position to the appropriate ram register.
}
}
HAL_LCD_UpdateDisplayRequest(&hlcd);
//HAL_Delay(1000);
}

void get_temp(){
//Trigger ADC conversion
HAL_ADC_Start(&hadc);
if (HAL_ADC_PollForConversion(&hadc, HAL_MAX_DELAY) == HAL_OK) {
adc_value = HAL_ADC_GetValue(&hadc);
// Convert ADC value to temperature using Steinhart-Hart equation with calibration factor
float resistance = REFERENCE_RESISTANCE * ((float)adc_value / 4095.0); // Calibration factor
float temperature_kelvin = 1.0 / (A_COEFF + B_COEFF * log(resistance) + C_COEFF * pow(log(resistance), 3));
float temperature_celsius = temperature_kelvin - 273.15;
DisplayNumber(temperature_celsius,0);

// Prepare the data to be transmitted serial USB
char buffer[100];
int len = sprintf(buffer, "Raw ADC Value: %4lu - Temperature: %.2f\r\n", adc_value, temperature_celsius);
//Transmit data through USB
CDC_Transmit_FS((uint8_t *)buffer, len);
}
}


//Function to test the DisplayNumber Function with various 'testNumbers' values
/* void testFunctionNumbers(){
double testNumbers[] = {-999, -99.9, -9.99, -9.01, -1.234, 0, 5.678, 99.99, 999, 9999};
int numTests = sizeof(testNumbers) / sizeof(testNumbers[0]);

for (int i = 0; i < numTests; i++) {
// char buffer[100];
// int len = sprintf(buffer, "Input: %7.2f", testNumbers[i]);
// CDC_Transmit_FS((uint8_t *)buffer, len);
HAL_LCD_Clear(&hlcd);
DisplayNumber(testNumbers[i],0);
HAL_Delay(5000);
}
}
*/

/* //iterative test
void testFunctionIterate(){
for(double testValue=-1000.01; testValue < 10010; (testValue = testValue + 0.01)){
// char buffer[100];
// int len = sprintf(buffer, "Input: %7.2f\r\n", testValue);
// CDC_Transmit_FS((uint8_t *)buffer, len);
HAL_LCD_Clear(&hlcd);
DisplayNumber(testValue,0);
HAL_Delay(10);
}
}
*/

/* //Segment Test
void testFunctionCharacters(){ // this function doesn't rely on the Display numbers function, it interfaces directly with the display RAM.
// This tests the display displaying one digit one each character position.
for(int j=0; j < 10; j++){ // count to ten
HAL_LCD_Clear(&hlcd);
for(int i=0; i < char_count; i++){ //For each Character:
// char buffer[100]; // communicate on the USB serial as each digit is written
// int len = sprintf(buffer, "char %d, number: %d, ASCII: 0x%2X\r\n", i, j, SevenSegmentASCII[j + 48]);
// CDC_Transmit_FS((uint8_t *)buffer, len);
for(uint8_t k=0; k<seg_count; k++){ //each segment gets written
int data = ((SevenSegmentASCII[j + 48] >> k) & 1); //bitshift to the 'í' segment and check if its a 1, (by ANDing segment with 1)
HAL_LCD_Write(&hlcd, seg_data[i][k].reg, 1 << seg_data[i][k].mask, data << seg_data[i][k].mask); //unmask all bits, and write that segments position to the appropriate ram register.
}
HAL_LCD_UpdateDisplayRequest(&hlcd);
HAL_Delay(1000);
}
}
}
*/

//init_display();
//init_sensors(); // not implemented yet
//testFunctionCharacters();
//testFunctionNumbers();
//testFunctionIterate();
get_temp();
HAL_Delay(500);

}
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI
                              |RCC_OSCILLATORTYPE_HSI48;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.LSIState = RCC_LSI_ON;
  RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_USB;
  PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
  PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief ADC Initialization Function
  * @param None
  * @retval None
  */
static void MX_ADC_Init(void)
{

  /* USER CODE BEGIN ADC_Init 0 */

  /* USER CODE END ADC_Init 0 */

  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC_Init 1 */

  /* USER CODE END ADC_Init 1 */

  /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
  */
  hadc.Instance = ADC1;
  hadc.Init.OversamplingMode = DISABLE;
  hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV1;
  hadc.Init.Resolution = ADC_RESOLUTION_12B;
  hadc.Init.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
  hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
  hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc.Init.ContinuousConvMode = DISABLE;
  hadc.Init.DiscontinuousConvMode = DISABLE;
  hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc.Init.DMAContinuousRequests = DISABLE;
  hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc.Init.LowPowerAutoWait = DISABLE;
  hadc.Init.LowPowerFrequencyMode = DISABLE;
  hadc.Init.LowPowerAutoPowerOff = DISABLE;
  if (HAL_ADC_Init(&hadc) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel to be converted.
  */
  sConfig.Channel = ADC_CHANNEL_5;
  sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
  if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC_Init 2 */

  /* USER CODE END ADC_Init 2 */

}

/**
  * @brief LCD Initialization Function
  * @param None
  * @retval None
  */
static void MX_LCD_Init(void)
{

  /* USER CODE BEGIN LCD_Init 0 */

  /* USER CODE END LCD_Init 0 */

  /* USER CODE BEGIN LCD_Init 1 */

  /* USER CODE END LCD_Init 1 */
  hlcd.Instance = LCD;
  hlcd.Init.Prescaler = LCD_PRESCALER_1;
  hlcd.Init.Divider = LCD_DIVIDER_16;
  hlcd.Init.Duty = LCD_DUTY_1_4;
  hlcd.Init.Bias = LCD_BIAS_1_4;
  hlcd.Init.VoltageSource = LCD_VOLTAGESOURCE_INTERNAL;
  hlcd.Init.Contrast = LCD_CONTRASTLEVEL_3;
  hlcd.Init.DeadTime = LCD_DEADTIME_0;
  hlcd.Init.PulseOnDuration = LCD_PULSEONDURATION_4;
  hlcd.Init.HighDrive = LCD_HIGHDRIVE_0;
  hlcd.Init.BlinkMode = LCD_BLINKMODE_OFF;
  hlcd.Init.BlinkFrequency = LCD_BLINKFREQUENCY_DIV8;
  hlcd.Init.MuxSegment = LCD_MUXSEGMENT_DISABLE;
  if (HAL_LCD_Init(&hlcd) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN LCD_Init 2 */

  /* USER CODE END LCD_Init 2 */

}

/**
  * @brief RTC Initialization Function
  * @param None
  * @retval None
  */
static void MX_RTC_Init(void)
{

  /* USER CODE BEGIN RTC_Init 0 */

  /* USER CODE END RTC_Init 0 */

  RTC_TimeTypeDef sTime = {0};
  RTC_DateTypeDef sDate = {0};

  /* USER CODE BEGIN RTC_Init 1 */

  /* USER CODE END RTC_Init 1 */

  /** Initialize RTC Only
  */
  hrtc.Instance = RTC;
  hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
  hrtc.Init.AsynchPrediv = 127;
  hrtc.Init.SynchPrediv = 255;
  hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
  hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
  hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
  hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
  if (HAL_RTC_Init(&hrtc) != HAL_OK)
  {
    Error_Handler();
  }

  /* USER CODE BEGIN Check_RTC_BKUP */

  /* USER CODE END Check_RTC_BKUP */

  /** Initialize RTC and set the Time and Date
  */
  sTime.Hours = 21;
  sTime.Minutes = 35;
  sTime.Seconds = 0;
  sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
  sTime.StoreOperation = RTC_STOREOPERATION_RESET;
  if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK)
  {
    Error_Handler();
  }
  sDate.WeekDay = RTC_WEEKDAY_MONDAY;
  sDate.Month = RTC_MONTH_JANUARY;
  sDate.Date = 29;
  sDate.Year = 0;

  if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN RTC_Init 2 */

  /* USER CODE END RTC_Init 2 */

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);

  /*Configure GPIO pin : PH0 */
  GPIO_InitStruct.Pin = GPIO_PIN_0;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);

  /*Configure GPIO pin : PA3 */
  GPIO_InitStruct.Pin = GPIO_PIN_3;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf