# HG changeset patch
# User Ideenmodellierer
# Date 1743363157 -7200
# Node ID aeafa631147db66289b24ac7af152c6b11f9b0fd
# Parent 41136649b90d771f75e86fdd8386c9dc7a6e06cb
Exchange shared files with Bootloader specific mini version
diff -r 41136649b90d -r aeafa631147d BootLoader/Src/display_mini.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/BootLoader/Src/display_mini.c Sun Mar 30 21:32:37 2025 +0200
@@ -0,0 +1,1163 @@
+
+#include "stm32f4xx_hal.h" /* for HAL_Delay() */
+#include "ostc.h"
+#include "display.h"
+
+#define TFT_ENABLE_EXTENDED_COMMANDS 0xB9
+#define TFT_SET_POWER 0xB1
+#define TFT_SLEEP_OUT 0x11
+#define TFT_DISPLAY_INVERSION_OFF 0x20
+#define TFT_MEMORY_ACCESS_ONTROL 0x36
+#define TFT_INTERFACE_PIXEL_FORMAT 0x3A
+#define TFT_SET_RGB_INTERFACE_RELATED 0xB3
+#define TFT_SET_DISPLAY_WAVEFORM 0xB4
+#define TFT_SET_PANEL 0xCC
+#define TFT_SET_GAMMA_CURVE_RELATED 0xE0
+#define TFT_DISPLAY_ON 0x29
+#define TFT_DISPLAY_OFF 0x28
+#define TFT_SLEEP_IN 0x10
+
+#define OLED_SCTE_SET_31h 0x31 // 0x0008
+#define OLED_WCWE_SET_32h 0x32 // 0x0014
+#define OLED_GATELESS1_30h 0x30 // 0x0002
+#define OLED_GATELESS2_27h 0x27 // 0x0000
+#define OLED_OSCILLATOR 0x11 // 0x00A1
+#define OLED_VBP_SET_12h 0x12 // 0x0008
+#define OLED_VFP_SET_13h 0x13 // 0x0008
+#define OLED_DISPLAY_CON_15h 0x15 // 0x0000
+#define OLED_COLOR_DEPTH_SET_16h 0x16 // 0x0000
+#define OLED_PENTILE_KEY_EFh 0xEF // 0x00D0 or 0x00E8
+#define OLED_PENTILE1_A0h 0xA0 // 0x0063
+#define OLED_PENTILE2_A1h 0xA1 // 0x00C0
+#define OLED_PENTILE3_A2h 0xA2 // 0x0032
+#define OLED_PENTILE4_A3h 0xA3 // 0x0002
+#define OLED_BRIGHTNESS_CTRL_39h 0x39 // 0044h
+// gamma table 0x40 - 0x66
+#define OLED_BOOSTING_FREQ 0x17 // 0x0022
+#define OLED_AMP_SET_18h 0x18 // 0x0033
+#define OLED_GAMMA_AMP_19h 0x19 // 0x0003
+#define OLED_POWER_CONTROL2_1Ah 0x1A // 0x0001
+#define OLED_POWER_CONTROL2_1Bh 0x1B //
+#define OLED_POWER_CONTROL2_1Ch 0x1C //
+#define OLED_INTERNAL_LOGIC_VOLTAGE 0x22 // VCC*0,65 = 3,3V * 0,55 = 0x00A2
+#define OLED_POWER_SET 0x23 // VC1OUT = VCI X 0.98 (default) = 0x00
+#define OLED_POWER_SET2 0x24 // VREG2OUT = 5,4V, VREG1OUT = 4,2V =0x77
+#define OLED_DISPLAY_CONDITION_SET_26h 0x26 // 0x00A0
+#define OLED_STB_BY_OFF_1Dh 0x1D // 00A0 + 300ms wait
+#define OLED_DDISP_ON_14h 0x14 // 0003
+
+static void Display_Error_Handler(void);
+static void display_power_on__2_of_2__post_RGB_display1(void);
+void display_1_brightness_max(void);
+void display_1_brightness_high(void);
+void display_1_brightness_std(void);
+void display_1_brightness_eco(void);
+void display_1_brightness_cave(void);
+
+uint8_t brightness_screen1;
+
+void display_power_on__1_of_2__pre_RGB(void)
+{
+ /* reset system */
+ HAL_GPIO_WritePin(DISPLAY_CSB_GPIO_PORT,DISPLAY_CSB_PIN,GPIO_PIN_SET); // chip select
+
+ HAL_GPIO_WritePin(DISPLAY_RESETB_GPIO_PORT,DISPLAY_RESETB_PIN,GPIO_PIN_RESET);
+ HAL_Delay(10);
+ HAL_GPIO_WritePin(DISPLAY_RESETB_GPIO_PORT,DISPLAY_RESETB_PIN,GPIO_PIN_SET);
+ HAL_Delay(25);
+
+ /* RGB signals should be now for 2 frames or more (datasheet) */
+}
+
+
+static void send(uint8_t *pData, uint16_t inputlength)
+{
+ HAL_GPIO_WritePin(DISPLAY_CSB_GPIO_PORT,DISPLAY_CSB_PIN,GPIO_PIN_RESET); // chip select
+
+ if(HAL_SPI_Transmit(&hspiDisplay,(uint8_t*)pData, inputlength, 10000) != HAL_OK)
+ Display_Error_Handler();
+
+ while (HAL_SPI_GetState(&hspiDisplay) != HAL_SPI_STATE_READY)
+ {
+ }
+ HAL_GPIO_WritePin(DISPLAY_CSB_GPIO_PORT,DISPLAY_CSB_PIN,GPIO_PIN_SET); // chip select
+}
+
+void display_power_off(void)
+{
+ uint8_t aTxBuffer[3];
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_DDISP_ON_14h;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+ HAL_Delay(25);
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_STB_BY_OFF_1Dh;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0xA1;
+ send((uint8_t*)aTxBuffer, 2);
+ HAL_Delay(200);
+ HAL_GPIO_WritePin(DISPLAY_RESETB_GPIO_PORT,DISPLAY_RESETB_PIN,GPIO_PIN_RESET);
+}
+
+
+void display_power_on__2_of_2__post_RGB(void)
+{
+ display_power_on__2_of_2__post_RGB_display1();
+}
+
+void display_power_on__2_of_2__post_RGB_display1(void)
+{
+ uint8_t aTxBuffer[3];
+
+ aTxBuffer[0] = 0x71; // Read chip Index & revision number
+ aTxBuffer[1] = 0x00; // Dummy write - reads out 0x27
+ aTxBuffer[1] = 0x00; // Dummy write - reads out 0x96
+ send((uint8_t*)aTxBuffer, 3);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_OSCILLATOR;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0xA4;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_SCTE_SET_31h;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x08;//8
+ send((uint8_t*)aTxBuffer, 2);
+
+ /*//debug read
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_SCTE_SET_31h;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x73; // Read internal register
+ aTxBuffer[1] = 0x00; // Dummy write - reads out 0x08 (The just-set OLED_SCTE_SET value)
+ send((uint8_t*)aTxBuffer, 2);
+ */
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_WCWE_SET_32h;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x14;//14
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_GATELESS1_30h;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x02;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_GATELESS2_27h;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x01;
+ send((uint8_t*)aTxBuffer, 2);
+
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_VBP_SET_12h;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x08;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_VFP_SET_13h;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x08;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_DISPLAY_CON_15h;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x01; //SS=0
+ //aTxBuffer[1] = 0x11; //SS=1
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_COLOR_DEPTH_SET_16h;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_PENTILE_KEY_EFh; // write-only register...
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0xD0;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0xE8;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_PENTILE1_A0h; // write-only register...
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x63;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_PENTILE2_A1h; // write-only register...
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0xC0; // SID1&SID0=00
+// aTxBuffer[1] = 0xC4; // SID1&SID0=01 CC C8 C4 C0
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_PENTILE3_A2h; // write-only register...
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x32;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_PENTILE4_A3h; // write-only register...
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x02;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_BRIGHTNESS_CTRL_39h;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x44;//44
+ send((uint8_t*)aTxBuffer, 2);
+
+
+ display_1_brightness_std(); // boot brightness
+
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_BOOSTING_FREQ;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x22;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_AMP_SET_18h;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x22;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_GAMMA_AMP_19h;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x02;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_POWER_CONTROL2_1Ah;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+
+ /*
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_POWER_CONTROL2_1Bh;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x4B;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_POWER_CONTROL2_1Ch;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x05;
+ send((uint8_t*)aTxBuffer, 2);
+ */
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_INTERNAL_LOGIC_VOLTAGE;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0xA2;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_POWER_SET;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_POWER_SET2;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x77;
+ send((uint8_t*)aTxBuffer, 2);
+
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_DISPLAY_CONDITION_SET_26h;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0xA0;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_STB_BY_OFF_1Dh;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0xA0;
+ send((uint8_t*)aTxBuffer, 2);
+
+ HAL_Delay(250);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = OLED_DDISP_ON_14h;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x03;
+ send((uint8_t*)aTxBuffer, 2);
+}
+
+void display_1_brightness_max(void)
+{
+ uint8_t aTxBuffer[3];
+
+ if (brightness_screen1 == 4)
+ {
+ // do nothing
+ }
+ else
+ {
+ // GAMMA L=250
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x40;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x41;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x3F;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x42;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x2A;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x43;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x27;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x44;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x27;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x45;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x1F;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x46;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x44;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x50;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x51;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x52;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x17;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x53;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x24;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x54;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x26;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x55;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x1F;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x56;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x43;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x60;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x61;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x3F;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x62;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x2A;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x63;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x25;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x64;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x24;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x65;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x1B;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x66;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x5C;
+ send((uint8_t*)aTxBuffer, 2);
+
+ brightness_screen1=4;
+ }
+}
+
+void display_1_brightness_high(void)
+{
+ uint8_t aTxBuffer[3];
+ if (brightness_screen1 == 3)
+ {
+ // do nothing
+ }
+ else
+ {
+ // GAMMA L=200
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x40;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x41;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x3F;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x42;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x2A;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x43;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x27;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x44;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x27;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x45;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x1F;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x46;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x44;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x50;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x51;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x52;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x17;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x53;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x24;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x54;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x26;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x55;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x1F;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x56;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x43;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x60;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x61;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x3F;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x62;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x2A;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x63;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x25;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x64;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x24;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x65;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x1B;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x66;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x5C;
+ send((uint8_t*)aTxBuffer, 2);
+
+ brightness_screen1=3;
+ }
+}
+
+
+void display_1_brightness_std(void)
+{
+ uint8_t aTxBuffer[3];
+
+ if (brightness_screen1 == 2)
+ {
+ // do nothing
+ }
+ else
+ {
+ // GAMMA L=150
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x40;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x41;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x3F;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x42;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x2D;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x43;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x29;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x44;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x28;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x45;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x23;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x46;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x37;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x50;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x51;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x52;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x0B;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x53;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x25;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x54;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x28;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x55;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x22;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x56;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x36;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x60;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x61;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x3F;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x62;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x2B;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x63;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x28;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x64;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x26;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x65;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x1F;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x66;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x4A;
+ send((uint8_t*)aTxBuffer, 2);
+
+ brightness_screen1=2;
+ }
+}
+
+void display_1_brightness_eco(void)
+{
+ uint8_t aTxBuffer[3];
+
+ if (brightness_screen1 == 1)
+ {
+ // do nothing
+ }
+ else
+ {
+ // GAMMA L=100
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x40;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x41;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x3F;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x42;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x30;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x43;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x2A;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x44;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x2B;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x45;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x24;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x46;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x2F;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x50;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x51;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x52;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x53;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x25;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x54;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x29;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x55;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x24;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x56;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x2E;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x60;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x61;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x3F;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x62;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x2F;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x63;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x29;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x64;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x29;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x65;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x21;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x66;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x3F;
+ send((uint8_t*)aTxBuffer, 2);
+
+ brightness_screen1=1;
+ }
+}
+
+void display_1_brightness_cave(void)
+{
+ uint8_t aTxBuffer[3];
+
+ if (brightness_screen1 == 0)
+ {
+ // do nothing
+ }
+ else
+ {
+ // GAMMA L=50
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x40;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x41;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x3F;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x42;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x3C;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x43;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x2C;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x44;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x2D;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x45;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x27;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x46;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x24;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x50;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x51;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x52;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x53;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x22;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x54;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x2A;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x55;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x27;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x56;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x23;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x60;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x00;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x61;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x3F;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x62;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x3B;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x63;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x2C;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x64;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x2B;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x65;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x24;
+ send((uint8_t*)aTxBuffer, 2);
+
+ aTxBuffer[0] = 0x70;
+ aTxBuffer[1] = 0x66;
+ send((uint8_t*)aTxBuffer, 2);
+ aTxBuffer[0] = 0x72;
+ aTxBuffer[1] = 0x31;
+ send((uint8_t*)aTxBuffer, 2);
+
+ brightness_screen1=0;
+ }
+}
+
+static void Display_Error_Handler(void)
+{
+ //while(1)
+ {
+ }
+}
diff -r 41136649b90d -r aeafa631147d BootLoader/Src/externCPU2bootloader_mini.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/BootLoader/Src/externCPU2bootloader_mini.c Sun Mar 30 21:32:37 2025 +0200
@@ -0,0 +1,294 @@
+/**
+ ******************************************************************************
+ * @file externCPU2bootloader.c Template
+ * @author heinrichs weikamp gmbh
+ * @version V0.0.1
+ * @date 23-Oct-2014
+ * @version V0.0.1
+ * @since 23-Oct-2014
+ * @brief Main Template to communicate with the second CPU in bootloader mode
+ * bootloader ROM build by ST and defined in AN4286
+ *
+ @verbatim
+ ==============================================================================
+ ##### How to use #####
+ ==============================================================================
+ @endverbatim
+ ******************************************************************************
+ * @attention
+ *
+ *
© COPYRIGHT(c) 2016 heinrichs weikamp
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx_hal.h"
+#include "stdio.h"
+#include "ostc.h"
+#include "settings.h"
+#include "externCPU2bootloader.h"
+#include "externLogbookFlash.h"
+#include "tComm.h"
+
+
+/* Exported variables --------------------------------------------------------*/
+
+/* Private types -------------------------------------------------------------*/
+
+/* Private variables ---------------------------------------------------------*/
+
+/* Private function prototypes -----------------------------------------------*/
+
+static uint8_t boot_sync_frame(void);
+static uint8_t boot_ack(void);
+static uint8_t boot_get_id(uint8_t *RxBuffer);
+static uint8_t boot_get_version(uint8_t *RxBuffer);
+static uint8_t boot_write_memory(uint32_t address, uint8_t length_minus_1, uint8_t *data);
+static uint8_t boot_erase_memory(void);
+static void Bootloader_send_command(uint8_t command);
+static void Bootloader_spi_single(uint8_t TxByte);
+static void Bootloader_spi(uint16_t lengthData, uint8_t *aTxBuffer, uint8_t *aRxBuffer);
+
+
+/* Exported functions --------------------------------------------------------*/
+
+uint8_t extCPU2bootloader_start(uint8_t *version, uint16_t *chipID)
+{
+ uint8_t aRxBuffer[256] = { 0 };
+
+ HAL_GPIO_WritePin(SMALLCPU_CSB_GPIO_PORT,SMALLCPU_CSB_PIN,GPIO_PIN_RESET);
+
+ boot_sync_frame();
+ boot_get_version(aRxBuffer);
+ *version = aRxBuffer[1];
+ HAL_Delay(10);
+ boot_get_id(aRxBuffer);
+ *chipID = ((uint16_t)aRxBuffer[2]) << 8;
+ *chipID += (uint16_t)aRxBuffer[3];
+ HAL_Delay(10);
+ if((*chipID == 0x431) && (*version > 10) && (*version < 32))
+ return 1;
+ else
+ return 0;
+}
+
+
+uint8_t extCPU2bootloader_internal(uint8_t* buffer, uint32_t length, char* display_text)
+{
+ uint8_t version = 0;
+ uint16_t chipID = 0;
+
+ if(!extCPU2bootloader_start(&version,&chipID))
+ return 0;
+ if(!boot_erase_memory())
+ return 0;
+ HAL_Delay(100);
+ uint16_t i=0;
+ uint32_t lengthsave = length;
+ uint8_t percent = 0;
+
+ while(length)
+ {
+ percent = (100 * (i * 256)) /lengthsave;
+ tComm_verlauf(percent);
+
+ if(length > 256)
+ {
+ if( !boot_write_memory(0x08000000 + (i * 256), 255, &buffer[i * 256]) )
+ return 0;;
+ length -= 256;
+
+ }
+ else
+ {
+ if(!boot_write_memory(0x08000000 + (i * 256), length - 1, &buffer[i * 256]))
+ return 0;
+ length = 0;
+ }
+ i++;
+ }
+ return 2;
+}
+
+
+uint8_t extCPU2bootloader(uint8_t* buffer, uint32_t length, char* display_text)
+{
+ uint8_t result = 0;
+
+ MX_SmallCPU_Reset_To_Boot();
+ result = extCPU2bootloader_internal(buffer,length,display_text);
+ MX_SmallCPU_Reset_To_Standard();
+ return result;
+}
+
+/* Private functions --------------------------------------------------------*/
+
+static uint8_t boot_sync_frame(void)
+{
+ Bootloader_spi_single(0x5a);
+ return boot_ack();
+}
+
+static uint8_t boot_get_version(uint8_t *RxBuffer)
+{
+ Bootloader_spi_single(0x5a);
+ Bootloader_send_command(0x01);
+ if(!boot_ack())
+ return 0;
+ Bootloader_spi(3, NULL, RxBuffer);
+ return boot_ack();
+}
+
+
+static uint8_t boot_get_id(uint8_t *RxBuffer)
+{
+ Bootloader_spi_single(0x5a);
+ Bootloader_send_command(0x02);
+ if(!boot_ack())
+ return 0;
+ Bootloader_spi(5, NULL, RxBuffer);
+ return boot_ack();
+}
+
+
+uint8_t boot_write_memory(uint32_t address, uint8_t length_minus_1, uint8_t *data)
+{
+ uint8_t addressNew[4];
+ uint8_t checksum = 0;
+ uint16_t length;
+
+ Bootloader_spi_single(0x5a);
+ Bootloader_send_command(0x31);
+ if(!boot_ack())
+ return 1;
+ HAL_Delay(5);
+ addressNew[0] = (uint8_t)((address >> 24) & 0xFF);
+ addressNew[1] = (uint8_t)((address >> 16) & 0xFF);
+ addressNew[2] = (uint8_t)((address >> 8) & 0xFF);
+ addressNew[3] = (uint8_t)((address >> 0) & 0xFF);
+ Bootloader_spi(4, addressNew, NULL);
+ checksum = 0;
+ checksum ^= addressNew[0];
+ checksum ^= addressNew[1];
+ checksum ^= addressNew[2];
+ checksum ^= addressNew[3];
+ Bootloader_spi_single(checksum);
+ if(!boot_ack())
+ return 0;
+ HAL_Delay(1);
+ Bootloader_spi_single(length_minus_1);
+ length = ((uint16_t)length_minus_1) + 1;
+ Bootloader_spi(length, data, NULL);
+ HAL_Delay(26);
+ checksum = 0;
+ checksum ^= length_minus_1;
+ for(int i=0;i© COPYRIGHT(c) 2015 heinrichs weikamp
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx_hal.h"
+#include "externLogbookFlash.h"
+#include "ostc.h"
+#include "settings.h"
+#include "gfx_engine.h"
+
+/* Private types -------------------------------------------------------------*/
+#define FLASHSTART 0x000000
+//#define FLASHSTOP 0x01FFFFFF all 32 MB with 4byte addressing
+#define FLASHSTOP 0x00FFFFFF
+//#define FLASHSTOP 0x3FFFFF
+#define RELEASE 1
+#define HOLDCS 0
+
+#define HEADER2OFFSET 0x400
+
+typedef enum{
+ EF_HEADER,
+ EF_SAMPLE,
+ EF_DEVICEDATA,
+ EF_VPMDATA,
+ EF_SETTINGS,
+ EF_FIRMWARE,
+ EF_FIRMWARE2,
+}which_ring_enum;
+
+
+typedef struct{
+uint8_t IsBusy:1;
+uint8_t IsWriteEnabled:1;
+uint8_t BlockProtect0:1;
+uint8_t BlockProtect1:1;
+uint8_t BlockProtect2:1;
+uint8_t BlockProtect3:1;
+uint8_t IsAutoAddressIncMode:1;
+uint8_t BlockProtectL:1;
+} extFlashStatusUbit8_t;
+
+typedef union{
+extFlashStatusUbit8_t ub;
+uint8_t uw;
+} extFlashStatusBit8_Type;
+
+
+/* Exported variables --------------------------------------------------------*/
+
+/* Private variables ---------------------------------------------------------*/
+
+static uint32_t actualAddress = 0;
+static uint32_t preparedPageAddress = 0;
+static uint32_t closeSectorAddress = 0;
+static uint32_t actualPointerHeader = 0;
+static uint32_t actualPointerSample = 0;
+static uint32_t actualPointerDevicedata = DDSTART;
+static uint32_t actualPointerVPM = 0;
+static uint32_t actualPointerSettings = SETTINGSSTART;
+static uint32_t actualPointerFirmware = 0;
+static uint32_t actualPointerFirmware2 = 0;
+
+/* Private function prototypes -----------------------------------------------*/
+static void chip_unselect(void);
+static void chip_select(void);
+static void write_spi(uint8_t data, uint8_t unselect_CS_afterwards);
+static uint8_t read_spi(uint8_t unselect_CS_afterwards);
+static void write_address(uint8_t unselect_CS_afterwards);
+static void Error_Handler_extflash(void);
+static void wait_chip_not_busy(void);
+static void ext_flash_incf_address(uint8_t type);
+//void ext_flash_incf_address_ring(void);
+
+static void ext_flash_erase4kB(void);
+static void ext_flash_erase32kB(void);
+static void ext_flash_erase64kB(void);
+static uint8_t ext_flash_erase_if_on_page_start(void);
+
+static void ef_write_block(uint8_t * sendByte, uint32_t length, uint8_t type, uint8_t do_not_erase);
+
+static void ext_flash_read_block(uint8_t *getByte, uint8_t type);
+static void ext_flash_read_block_multi(void *getByte, uint32_t size, uint8_t type);
+static void ext_flash_read_block_stop(void);
+
+static void ef_hw_rough_delay_us(uint32_t delayUs);
+static void ef_erase_64K(uint32_t blocks);
+
+
+/* Exported functions --------------------------------------------------------*/
+
+void ext_flash_write_firmware(uint8_t *pSample1, uint32_t length1)//, uint8_t *pSample2, uint32_t length2)
+{
+ general32to8_Type lengthTransform;
+
+ lengthTransform.u32 = length1;
+
+ actualPointerFirmware = FWSTART;
+ ef_write_block(lengthTransform.u8,4, EF_FIRMWARE, 1);
+ ef_write_block(pSample1,length1, EF_FIRMWARE, 1);
+
+// if(length2)
+// ef_write_block(pSample2,length2, EF_FIRMWARE, 1);
+}
+
+uint8_t ext_flash_read_firmware_version(char *text)
+{
+ uint32_t backup = actualAddress;
+ uint8_t buffer[4];
+
+ // + 4 for length data, see ext_flash_write_firmware
+ actualAddress = FWSTART + 4 + 0x10000;
+ ext_flash_read_block_start();
+ ext_flash_read_block(&buffer[0], EF_FIRMWARE);
+ ext_flash_read_block(&buffer[1], EF_FIRMWARE);
+ ext_flash_read_block(&buffer[2], EF_FIRMWARE);
+ ext_flash_read_block(&buffer[3], EF_FIRMWARE);
+
+ ext_flash_read_block_stop();
+ actualAddress = backup;
+
+ uint8_t ptr = 0;
+ text[ptr++] = 'V';
+ ptr += gfx_number_to_string(2,0,&text[ptr],buffer[0] & 0x3F);
+ text[ptr++] = '.';
+ ptr += gfx_number_to_string(2,0,&text[ptr],buffer[1] & 0x3F);
+ text[ptr++] = '.';
+ ptr += gfx_number_to_string(2,0,&text[ptr],buffer[2] & 0x3F);
+ text[ptr++] = ' ';
+ if(buffer[3])
+ {
+ text[ptr++] = 'b';
+ text[ptr++] = 'e';
+ text[ptr++] = 't';
+ text[ptr++] = 'a';
+ text[ptr++] = ' ';
+ }
+ return ptr;
+}
+
+
+uint32_t ext_flash_read_firmware(uint8_t *pSample1, uint32_t max_length, uint8_t *magicByte)
+{
+ uint32_t backup = actualAddress;
+ general32to8_Type lengthTransform;
+
+ actualAddress = FWSTART;
+ ext_flash_read_block_start();
+
+ ext_flash_read_block(&lengthTransform.u8[0], EF_FIRMWARE);
+ ext_flash_read_block(&lengthTransform.u8[1], EF_FIRMWARE);
+ ext_flash_read_block(&lengthTransform.u8[2], EF_FIRMWARE);
+ ext_flash_read_block(&lengthTransform.u8[3], EF_FIRMWARE);
+
+
+ if(lengthTransform.u32 == 0xFFFFFFFF)
+ {
+ lengthTransform.u32 = 0xFFFFFFFF;
+ }
+ else
+ if(lengthTransform.u32 > max_length)
+ {
+ lengthTransform.u32 = 0xFF000000;
+ }
+ else
+ {
+ for(uint32_t i = 0; i max_length1 + max_length2)
+ {
+ lengthTransform.u32 = 0xFF000000;
+ }
+ else
+ {
+ if(lengthTransform.u32 < max_length1)
+ {
+ length1 = lengthTransform.u32;
+ length2 = 0;
+ }
+ else
+ {
+ length1 = max_length1;
+ length2 = lengthTransform.u32 - max_length1;
+ }
+
+ if(pSample1)
+ {
+ for(uint32_t i = 0; i> 24) & 0xFF;
+ buffer[count++] = transfer;
+ transfer = (data[i].value_int32 >> 16) & 0xFF;
+ buffer[count++] = transfer;
+ transfer = (data[i].value_int32 >> 8) & 0xFF;
+ buffer[count++] = transfer;
+ transfer = (data[i].value_int32) & 0xFF;
+ buffer[count++] = transfer;
+
+ translateDate(data[i].date_rtc_dr, &Sdate);
+ translateTime(data[i].time_rtc_tr, &Stime);
+ buffer[count++] = Sdate.Year;
+ buffer[count++] = Sdate.Month;
+ buffer[count++] = Sdate.Date;
+ buffer[count++] = Stime.Hours;
+ }
+}
+
+void ext_flash_erase_firmware(void)
+{
+ uint32_t size, blocks_64k;
+
+ actualAddress = FWSTART;
+ size = 1 + FWSTOP - FWSTART;
+ blocks_64k = size / 0x10000;
+ ef_erase_64K(blocks_64k);
+}
+
+void ext_flash_erase_firmware2(void)
+{
+ uint32_t size, blocks_64k;
+
+ actualAddress = FWSTART2;
+ size = 1 + FWSTOP2 - FWSTART2;
+ blocks_64k = size / 0x10000;
+ ef_erase_64K(blocks_64k);
+}
+
+
+
+static void ext_flash_erase4kB(void)
+{
+ wait_chip_not_busy();
+ write_spi(0x06,RELEASE);/* WREN */
+ write_spi(0x20,HOLDCS);/* sector erase cmd */
+ write_address(RELEASE);
+}
+
+/* be careful - might not work with entire family and other products
+ * see page 14 of LOGBOOK_V3_S25FS-S_00-271247.pdf
+ */
+static void ext_flash_erase32kB(void)
+{
+ uint32_t actualAddress_backup;
+
+ actualAddress_backup = actualAddress;
+ actualAddress = 0;
+ wait_chip_not_busy();
+ write_spi(0x06,RELEASE);/* WREN */
+ write_spi(0xD8,HOLDCS);/* sector erase cmd */
+ write_address(RELEASE);
+ actualAddress = actualAddress_backup;
+}
+
+
+static void ext_flash_erase64kB(void)
+{
+ wait_chip_not_busy();
+ write_spi(0x06,RELEASE);/* WREN */
+ write_spi(0xD8,HOLDCS);/* sector erase cmd */
+ write_address(RELEASE);
+}
+
+
+void ext_flash_read_block_start(void)
+{
+ wait_chip_not_busy();
+ write_spi(0x03,HOLDCS); /* WREN */
+ write_address(HOLDCS);
+}
+
+/* 4KB, 32KB, 64 KB, not the upper 16 MB with 4 Byte address at the moment */
+static uint8_t ext_flash_erase_if_on_page_start(void)
+{
+ if(actualAddress < 0x00008000)
+ {
+ /* 4K Byte is 0x1000 */
+ if((actualAddress & 0xFFF) == 0)
+ {
+ ext_flash_erase4kB();
+ return 1;
+ }
+ }
+ else
+ if(actualAddress < 0x00010000)
+ {
+ /* 32K Byte is only one page */
+ if(actualAddress == 0x00010000)
+ {
+ ext_flash_erase32kB();
+ return 1;
+ }
+ }
+ else
+ {
+ /* 64K Byte is 0x10000 */
+ if((actualAddress & 0xFFFF) == 0)
+ {
+ if(preparedPageAddress == actualAddress) /* has page already been prepared before? (at the moment for samples only) */
+ {
+ preparedPageAddress = 0;
+
+ }
+ else
+ {
+ ext_flash_erase64kB();
+ }
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+static void ext_flash_read_block(uint8_t *getByte, uint8_t type)
+{
+ *getByte = read_spi(HOLDCS);/* read data */
+ ext_flash_incf_address(type);
+}
+
+
+static void ext_flash_read_block_multi(void *getByte, uint32_t size, uint8_t type)
+{
+ uint8_t *data;
+ data = getByte;
+
+ for(uint32_t i=0;i= 256)
+ {
+ remaining_length = 255; /* up to 256 bytes may be written in one burst. Last byte is written with release */
+ }
+ else
+ {
+ remaining_length--; /* last byte needed for release */
+ }
+ if(remaining_length >= (remaining_page_size) ) /* use 256 byte page and calculate number of bytes left */
+ {
+ remaining_length = remaining_page_size - 1;
+ }
+ if( (remaining_space_to_ring_end >= 256))
+ {
+ for(int j=0; j ringStop)
+ actualAddress = ringStart;
+
+ if(do_not_erase == 0)
+ ext_flash_erase_if_on_page_start();
+ }
+ switch(type)
+ {
+ case EF_HEADER:
+ actualPointerHeader = actualAddress;
+ break;
+ case EF_SAMPLE:
+ actualPointerSample = actualAddress;
+ break;
+ case EF_DEVICEDATA:
+ actualPointerDevicedata = actualAddress;
+ break;
+ case EF_VPMDATA:
+ actualPointerVPM = actualAddress;
+ break;
+ case EF_SETTINGS:
+ actualPointerSettings = actualAddress;
+ break;
+ case EF_FIRMWARE:
+ actualPointerFirmware = actualAddress;
+ break;
+ case EF_FIRMWARE2:
+ actualPointerFirmware2 = actualAddress;
+ break;
+ default:
+ break;
+ }
+}
+
+
+static void ef_erase_64K(uint32_t blocks)
+{
+ for(uint32_t i = 0; i < blocks; i++)
+ {
+ wait_chip_not_busy();
+ write_spi(0x06,RELEASE);/* WREN */
+ write_spi(0xD8,HOLDCS);/* 64k erase cmd */
+ write_address(RELEASE);
+ actualAddress += 0x10000;
+ HAL_Delay(25);
+ }
+}
+
+static void chip_unselect(void)
+{
+ HAL_GPIO_WritePin(EXTFLASH_CSB_GPIO_PORT,EXTFLASH_CSB_PIN,GPIO_PIN_SET); // chip select
+}
+
+static void chip_select(void)
+{
+ HAL_GPIO_WritePin(EXTFLASH_CSB_GPIO_PORT,EXTFLASH_CSB_PIN,GPIO_PIN_RESET); // chip select
+}
+
+static uint8_t read_spi(uint8_t unselect_CS_afterwards)
+{
+ uint8_t byte;
+
+ chip_select();
+
+ if(HAL_SPI_Receive(&hspiDisplay, &byte, 1, 10000) != HAL_OK)
+ Error_Handler_extflash();
+
+ while (HAL_SPI_GetState(&hspiDisplay) != HAL_SPI_STATE_READY)
+ {
+ }
+ if(unselect_CS_afterwards)
+ chip_unselect();
+
+ return byte;
+}
+
+
+static void write_spi(uint8_t data, uint8_t unselect_CS_afterwards)
+{
+ chip_select();
+
+ if(HAL_SPI_Transmit(&hspiDisplay, &data, 1, 10000) != HAL_OK)
+ Error_Handler_extflash();
+
+ while (HAL_SPI_GetState(&hspiDisplay) != HAL_SPI_STATE_READY)
+ {
+ }
+ if(unselect_CS_afterwards)
+ chip_unselect();
+}
+
+
+static void write_address(uint8_t unselect_CS_afterwards)
+{
+ uint8_t hi, med ,lo;
+
+ hi = (actualAddress >> 16) & 0xFF;
+ med = (actualAddress >> 8) & 0xFF;
+ lo = actualAddress & 0xFF;
+
+ write_spi(hi, HOLDCS);
+ write_spi(med, HOLDCS);
+ write_spi(lo, unselect_CS_afterwards);
+}
+
+
+static void wait_chip_not_busy(void)
+{
+ uint8_t status;
+
+ chip_unselect();
+
+ write_spi(0x05,HOLDCS); /* RDSR */
+ status = read_spi(HOLDCS);/* read status */
+ while(status & 0x01)
+ {
+ HAL_Delay(1);
+ status = read_spi(HOLDCS);/* read status */
+ }
+ chip_unselect();
+}
+
+
+static void ext_flash_incf_address(uint8_t type)
+{
+ uint32_t ringStart, ringStop;
+
+ actualAddress += 1;
+
+ switch(type)
+ {
+ case EF_HEADER:
+ ringStart = HEADERSTART;
+ ringStop = HEADERSTOP;
+ break;
+ case EF_SAMPLE:
+ ringStart = SAMPLESTART;
+ ringStop = SAMPLESTOP;
+ break;
+ case EF_DEVICEDATA:
+ ringStart = DDSTART;
+ ringStop = DDSTOP;
+ break;
+ case EF_VPMDATA:
+ ringStart = VPMSTART;
+ ringStop = VPMSTOP;
+ break;
+ case EF_SETTINGS:
+ ringStart = SETTINGSSTART;
+ ringStop = SETTINGSSTOP;
+ break;
+ case EF_FIRMWARE:
+ ringStart = FWSTART;
+ ringStop = FWSTOP;
+ break;
+ case EF_FIRMWARE2:
+ ringStart = FWSTART2;
+ ringStop = FWSTOP2;
+ break;
+ default:
+ ringStart = FLASHSTART;
+ ringStop = FLASHSTOP;
+ break;
+ }
+
+ if((actualAddress < ringStart) || (actualAddress > ringStop))
+ actualAddress = ringStart;
+}
+
+static void ef_hw_rough_delay_us(uint32_t delayUs)
+{
+ if(!delayUs)
+ return;
+ delayUs*= 12;
+ while(delayUs--);
+ return;
+}
+
+static void Error_Handler_extflash(void)
+{
+ while(1)
+ {
+ }
+}
+
+void ext_flash_CloseSector(void)
+{
+ uint32_t actualAddressBackup = actualAddress;
+ int i=0;
+
+ if(closeSectorAddress != 0)
+ {
+ /* write some dummy bytes to the sector which is currently used for storing samples. This is done to "hide" problem if function is calles again */
+ actualAddress = closeSectorAddress;
+
+ wait_chip_not_busy();
+ write_spi(0x06,RELEASE); /* WREN */
+ write_spi(0x02,HOLDCS); /* write cmd */
+ write_address(HOLDCS);
+ for(i = 0; i<8; i++)
+ {
+ write_spi(0xA5,HOLDCS);/* write data */
+ actualAddress++;
+ }
+ /* byte with RELEASE */
+ write_spi(0xA5,RELEASE);/* write data */
+ actualAddress = actualAddressBackup;
+ closeSectorAddress = 0;
+ }
+}
+
+
+uint8_t ext_flash_erase_firmware_if_not_empty(void)
+{
+ const uint8_t TESTSIZE_FW = 4;
+
+ uint8_t data[TESTSIZE_FW];
+ uint8_t notEmpty = 0;
+
+ actualAddress = FWSTART;
+ ext_flash_read_block_start();
+ for(int i = 0; i < TESTSIZE_FW; i++)
+ {
+ ext_flash_read_block(&data[i], EF_FIRMWARE);
+ if(data[i] != 0xFF)
+ notEmpty = 1;
+ }
+ ext_flash_read_block_stop();
+
+ if(notEmpty)
+ {
+ ext_flash_erase_firmware();
+ return 1;
+ }
+ else
+ return 0;
+}
+
+uint8_t ext_flash_erase_firmware2_if_not_empty(void)
+{
+ const uint8_t TESTSIZE_FW = 4;
+
+ uint8_t data[TESTSIZE_FW];
+ uint8_t notEmpty = 0;
+
+ actualAddress = FWSTART2;
+ ext_flash_read_block_start();
+ for(int i = 0; i < TESTSIZE_FW; i++)
+ {
+ ext_flash_read_block(&data[i], EF_FIRMWARE2);
+ if(data[i] != 0xFF)
+ notEmpty = 1;
+ }
+ ext_flash_read_block_stop();
+
+ if(notEmpty)
+ {
+ ext_flash_erase_firmware2();
+ return 1;
+ }
+ else
+ return 0;
+}
diff -r 41136649b90d -r aeafa631147d BootLoader/Src/gfx_engine_mini.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/BootLoader/Src/gfx_engine_mini.c Sun Mar 30 21:32:37 2025 +0200
@@ -0,0 +1,3352 @@
+/**
+ ******************************************************************************
+ * @file gfx_engine.c
+ * @author heinrichs weikamp gmbh
+ * @version V0.0.2
+ * @date 30-April-2014
+ * @brief Main source file of GFX Graphic Engine
+ * This file provides firmware functions to manage the following
+ * functions to draw on the screen:
+ * + write string to display
+ *
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT(c) 2014 heinrichs weikamp
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+
+#include
+#include
+
+#include "stm32f4xx_hal.h"
+
+#include "gfx.h"
+#include "gfx_engine.h"
+#include "gfx_fonts.h"
+#include "gfx_colors.h"
+#include "ostc.h"
+#include "settings.h"
+#include "text_multilanguage.h"
+
+/* Exported variables --------------------------------------------------------*/
+
+/* Private types -------------------------------------------------------------*/
+
+#define RING_BUF_SIZE (5u)
+#define MAX_COLOR_STRING_LENGTH (100u)
+
+typedef struct
+{
+ uint32_t Xdelta;
+ uint32_t Ydelta;
+ uint8_t invert;
+ uint8_t color;
+ uint8_t dualFont;
+ uint8_t resize;
+ uint32_t font;
+ uint8_t spaceMode;
+ uint8_t singleSpaceWithSizeOfNextChar;
+ uint8_t useTinyFont;
+ uint32_t TinyFont;
+ int8_t TinyFontExtraYdelta;
+ tFont *actualFont;
+ uint8_t doubleSize;
+} GFX_CfgWriteString;
+
+typedef struct
+{
+ uint32_t pBuffer;
+ uint32_t height;
+ uint32_t width;
+ uint32_t leftStart;
+ uint32_t bottomStart;
+} GFX_layerSingle;
+/*
+typedef struct
+{
+ GFX_layerSingle top;
+ GFX_layerSingle bottom;
+} GFX_layersTopBottom;
+*/
+typedef struct
+{
+ uint32_t pActualTopBuffer;
+ uint32_t pNextTopBuffer[RING_BUF_SIZE];
+ GFX_layerSingle actualBottom;
+ GFX_layerSingle nextBottom[RING_BUF_SIZE];
+ uint8_t NextTopWrite;
+ uint8_t NextBottomWrite;
+ uint8_t NextTopRead;
+ uint8_t NextBottomRead;
+} GFX_layerControl;
+
+typedef struct
+{
+ uint32_t StartAddress;
+ int8_t status;
+ uint8_t caller;
+} SFrameList;
+
+enum FRAMESTATE
+{
+ CLEAR = 0,
+ BLOCKED,
+ RELEASED
+};
+
+enum LOGOSTATE
+{
+ LOGOOFF = 0,
+ LOGOSTART = 1,
+ LOGOSTOP = 255
+};
+
+// should be 43
+#define MAXFRAMES 39
+
+#define SDRAM_BANK_ADDR ((uint32_t)0xD0000000)
+#define FBGlobalStart SDRAM_BANK_ADDR
+#define FBOffsetEachIndex (800*480*2)
+
+#define SDRAM_DOUBLE_BUFFER_ONE ((uint32_t)(FBGlobalStart + (MAXFRAMES * FBOffsetEachIndex)))
+#define SDRAM_DOUBLE_BUFFER_TWO ((uint32_t)(SDRAM_DOUBLE_BUFFER_ONE + (2 * FBOffsetEachIndex)))
+#define SDRAM_DOUBLE_BUFFER_END ((uint32_t)(SDRAM_DOUBLE_BUFFER_TWO + (2 * FBOffsetEachIndex)))
+
+/* Semi Private variables ---------------------------------------------------------*/
+
+DMA2D_HandleTypeDef Dma2dHandle;
+static LTDC_HandleTypeDef LtdcHandle;
+
+/* Private variables ---------------------------------------------------------*/
+
+static uint8_t DMA2D_at_work = 0;
+
+static GFX_layerControl FrameHandler = { 0 };
+
+static uint32_t pInvisibleFrame = 0;
+static uint32_t pLogoFrame = 0;
+static uint8_t logoStatus;
+static uint32_t pBackgroundHwFrame = 0;
+static uint8_t backgroundHwStatus;
+
+static SFrameList frame[MAXFRAMES];
+
+static void GFX_clear_frame_immediately(uint32_t pDestination);
+static void GFX_draw_image_color(GFX_DrawCfgScreen *hgfx, SWindowGimpStyle window, const tImage *image);
+/* ITM Trace-----------------------------------------------------------------*/
+
+#include "stdio.h"
+
+#define ITM_Port8(n) (*((volatile unsigned char *)(0xE0000000+4*n)))
+#define ITM_Port16(n) (*((volatile unsigned short*)(0xE0000000+4*n)))
+#define ITM_Port32(n) (*((volatile unsigned long *)(0xE0000000+4*n)))
+
+#define DEMCR (*((volatile unsigned long *)(0xE000EDFC)))
+#define TRCENA 0x01000000
+
+struct __FILE { int handle; /* Add whatever needed */ };
+FILE __stdout;
+FILE __stdin;
+
+int fputc(int ch, FILE *f) {
+ if (DEMCR & TRCENA) {
+ while (ITM_Port32(0) == 0);
+ ITM_Port8(0) = ch;
+ }
+ return(ch);
+}
+
+uint32_t MinU32GFX(uint32_t a, uint32_t b)
+{
+ return ((ab)?a:b);
+}
+
+/* Private function prototypes -----------------------------------------------*/
+
+static uint32_t GFX_write_char(GFX_DrawCfgWindow* hgfx, GFX_CfgWriteString* cfg, uint8_t character, tFont *Font);
+static uint32_t GFX_write_substring(GFX_CfgWriteString* cfg, GFX_DrawCfgWindow* hgfx, uint8_t textId, int8_t nextCharFor2Byte);
+static uint32_t GFX_write__Modify_Xdelta__Centered(GFX_CfgWriteString* cfg, GFX_DrawCfgWindow* hgfx, const char *pText);
+static uint32_t GFX_write__Modify_Xdelta__RightAlign(GFX_CfgWriteString* cfg, GFX_DrawCfgWindow* hgfx, const char *pTextInput);
+static void GFX_Error_Handler(void);
+static void GFX_Dma2d_TransferComplete(DMA2D_HandleTypeDef* Dma2dHandle);
+static void GFX_Dma2d_TransferError(DMA2D_HandleTypeDef* Dma2dHandle);
+static void GFX_clear_frame_dma2d(uint8_t frameId);
+
+static uint32_t GFX_doubleBufferOne(void);
+static uint32_t GFX_doubleBufferTwo(void);
+
+static void GFX_LTDC_Init_display1(void);
+
+
+/* Exported functions --------------------------------------------------------*/
+
+uint8_t GFX_logoStatus(void)
+{
+ return logoStatus;
+}
+
+void GFX_SetWindowLayer0(uint32_t pDestination, int16_t XleftGimpStyle, int16_t XrightGimpStyle, int16_t YtopGimpStyle, int16_t YbottomGimpStyle)
+{
+ int16_t XSize, YSize, X0, Y0;
+
+ if(XleftGimpStyle < 0) XleftGimpStyle = 0;
+ if(XrightGimpStyle < 0) XrightGimpStyle = 0;
+ if(XleftGimpStyle > 799) XleftGimpStyle = 800;
+ if(XrightGimpStyle > 799) XrightGimpStyle = 800;
+
+ if(YtopGimpStyle < 0) YtopGimpStyle = 0;
+ if(YbottomGimpStyle < 0) YbottomGimpStyle = 0;
+ if(YtopGimpStyle > 479) YtopGimpStyle = 480;
+ if(YbottomGimpStyle > 479) YbottomGimpStyle = 480;
+
+/*
+ XSize = YbottomGimpStyle - YtopGimpStyle;
+ YSize = XrightGimpStyle - XleftGimpStyle;
+ if((XSize <= 0) || (YSize <= 0))
+ return;
+ X0 = 479 - YbottomGimpStyle;
+ Y0 = XleftGimpStyle;
+ while((LTDC->CPSR & LTDC_CPSR_CYPOS) <= (uint32_t)800);
+ HAL_LTDC_SetWindowSize(&LtdcHandle, XSize, YSize, LayerIdx);
+ HAL_LTDC_SetWindowPosition(&LtdcHandle, X0, Y0,LayerIdx);
+ HAL_LTDC_SetAddress(&LtdcHandle, pDestination, LayerIdx);
+*/
+
+ XSize = XrightGimpStyle - XleftGimpStyle;
+ YSize = YbottomGimpStyle - YtopGimpStyle;
+ if((XSize <= 0) || (YSize <= 0))
+ return;
+ Y0 = 479 - YbottomGimpStyle;
+ X0 = XleftGimpStyle;
+
+ GFX_SetFrameBottom(pDestination, X0, Y0, XSize, YSize);
+}
+
+
+void GFX_logoAutoOff(void)
+{
+ if(logoStatus == LOGOOFF)
+ logoStatus = LOGOSTART;
+}
+
+
+void GFX_hwBackgroundOn(void)
+{
+ backgroundHwStatus = LOGOSTART;
+}
+
+
+void GFX_hwBackgroundOff(void)
+{
+ backgroundHwStatus = LOGOSTOP;
+}
+
+void GFX_build_hw_background_frame(void)
+{
+ GFX_DrawCfgScreen tLogoTemp;
+ SWindowGimpStyle windowGimp;
+
+ pBackgroundHwFrame = getFrame(1);
+ backgroundHwStatus = 0;
+
+ tLogoTemp.FBStartAdress = pBackgroundHwFrame;
+ tLogoTemp.ImageHeight = 480;
+ tLogoTemp.ImageWidth = 800;
+ tLogoTemp.LayerIndex = 1;
+
+ windowGimp.left = (800 - 400) / 2;
+ windowGimp.top = 0;//(480 - 46) / 2;
+
+ GFX_draw_image_color(&tLogoTemp, windowGimp, &ImgHWcolor);
+/*
+ char localtext[256];
+ uint8_t ptr = 0;
+
+ localtext[ptr++] = ' ';
+ localtext[ptr++] = ' ';
+ localtext[ptr++] = 'O';
+ localtext[ptr++] = 'S';
+ localtext[ptr++] = ' ';
+ ptr += GFX_printf_firmware(&localtext[ptr]);
+ localtext[ptr] = 0;
+
+ write_content_simple(&tLogoTemp, 0, 800, 240-24, &FontT24,localtext,CLUT_Font020);
+*/
+}
+
+
+void GFX_build_logo_frame(void)
+{
+ GFX_DrawCfgScreen tLogoTemp;
+ SWindowGimpStyle windowGimp;
+
+ pLogoFrame = getFrame(1);
+ logoStatus = LOGOOFF;
+
+ tLogoTemp.FBStartAdress = pLogoFrame;
+ tLogoTemp.ImageHeight = 480;
+ tLogoTemp.ImageWidth = 800;
+ tLogoTemp.LayerIndex = 1;
+
+ windowGimp.left = (800 - 400) / 2;
+ windowGimp.top = (480 - 46) / 2;
+
+ GFX_draw_image_color(&tLogoTemp, windowGimp, &ImgHWcolor);
+/*
+ char localtext[256];
+ uint8_t ptr = 0;
+
+ localtext[ptr++] = ' ';
+ localtext[ptr++] = ' ';
+ localtext[ptr++] = 'O';
+ localtext[ptr++] = 'S';
+ localtext[ptr++] = ' ';
+ ptr += GFX_printf_firmware(&localtext[ptr]);
+ localtext[ptr] = 0;
+
+ write_content_simple(&tLogoTemp, 0, 800, 240-24, &FontT24,localtext,CLUT_Font020);
+*/
+}
+
+void GFX_init(uint32_t * pDestinationOut)
+{
+ frame[0].StartAddress = FBGlobalStart;
+ GFX_clear_frame_immediately(frame[0].StartAddress);
+ frame[0].status = CLEAR;
+ frame[0].caller = 0;
+
+ for(int i=1;i 3)
+ colorscheme = 0;
+
+ ColorSchemeStart = CLUT_Colorscheme0 + (8 * colorscheme);
+ for(int i=1; i<8; i++)
+ {
+ ColorLUT[CLUT_Font027 + i] = ColorLUT[ColorSchemeStart + i];
+ }
+ change_CLUT_entry(CLUT_Font027, ColorSchemeStart);
+}
+
+
+void GFX_VGA_transform(uint32_t pSource, uint32_t pDestination)
+{
+ int h, v;
+ uint32_t offsetSource, offsetSourceStartOfLine;
+
+ offsetSourceStartOfLine = 480 + 480 - 2;
+ for(v=0;v<480;v++)
+ {
+ offsetSource = offsetSourceStartOfLine;
+ for(h=0;h<640;h++)
+ {
+ *(__IO uint8_t*)pDestination = *(uint8_t*)(pSource + offsetSource);
+ pDestination++;
+ offsetSource += 1;
+ *(__IO uint8_t*)pDestination = *(uint8_t*)(pSource + offsetSource);
+ pDestination++;
+ offsetSource += 480 + 479;
+ }
+ offsetSourceStartOfLine -= 2;
+ }
+}
+
+
+static void GFX_clear_frame_immediately(uint32_t pDestination)
+{
+ uint32_t i;
+ uint32_t* pfill = (uint32_t*) pDestination;
+
+
+ for(i = 200*480; i > 0; i--)
+ {
+ *pfill++ = 0;
+ *pfill++ = 0;
+ }
+}
+
+
+void GFX_clear_window_immediately(GFX_DrawCfgWindow* hgfx)
+{
+ uint32_t pDestination, i, j;
+ uint16_t left, width, bottom, height, nextlineStep;
+
+ pDestination = (uint32_t)hgfx->Image->FBStartAdress;
+
+ left = hgfx->WindowX0;
+ width = 1 + hgfx->WindowX1 - left;
+ bottom = hgfx->WindowY0;
+ height = 1 + hgfx->WindowY1 - bottom;
+ nextlineStep = hgfx->Image->ImageHeight - height;
+ nextlineStep *= 2;
+
+ pDestination += 2 * bottom;
+ pDestination += 2 * hgfx->Image->ImageHeight * left;
+
+ for(j = width; j > 0; j--)
+ {
+ for(i = height; i > 0; i--)
+ {
+ *(__IO uint16_t*)pDestination = 0;
+ pDestination += 2;
+ }
+ pDestination += nextlineStep;
+ }
+}
+
+
+static void GFX_clear_frame_dma2d(uint8_t frameId)
+{
+ if(frameId >= MAXFRAMES)
+ return;
+
+ DMA2D_at_work = frameId;
+
+ if (HAL_DMA2D_Start_IT(&Dma2dHandle, 0x0000000000, frame[frameId].StartAddress, 480, 800) != HAL_OK)
+ GFX_Error_Handler();
+}
+
+
+void GFX_fill_buffer(uint32_t pDestination, uint8_t alpha, uint8_t color)
+{
+
+ union al88_u
+ {
+ uint8_t al8[2];
+ uint16_t al88;
+ };
+ union al88_u colorcombination;
+ uint32_t i;
+ uint32_t* pfill = (uint32_t*) pDestination;
+ uint32_t fillpattern;
+
+ colorcombination.al8[0] = color;
+ colorcombination.al8[1] = alpha;
+
+ fillpattern = (colorcombination.al88 << 16) | colorcombination.al88;
+ for(i = 800*480/2; i > 0; i--)
+ {
+ *pfill++ = fillpattern;
+ }
+}
+
+static void GFX_draw_image_color(GFX_DrawCfgScreen *hgfx, SWindowGimpStyle window, const tImage *image)
+{
+ uint16_t* pDestination;
+
+ uint32_t j;
+ point_t start, stop;
+
+ start.x = window.left;
+ start.y = (hgfx->ImageHeight - image->height - window.top);
+ stop.y = start.y + image->height;
+ stop.x = start.x + image->width;
+ j = 0;
+
+ for(int xx = start.x; xx < stop.x; xx++)
+ {
+ pDestination = (uint16_t*)hgfx->FBStartAdress;
+ pDestination += xx * hgfx->ImageHeight;
+ pDestination += start.y;
+ for(int yy = start.y; yy < stop.y; yy++)
+ {
+ *(__IO uint16_t*)pDestination++ = 0xFF << 8 | image->data[j++];
+ }
+ }
+}
+
+
+/* this is NOT fast nor optimized */
+static void GFX_draw_pixel(GFX_DrawCfgScreen *hgfx, int16_t x, int16_t y, uint8_t color)
+{
+ uint16_t* pDestination;
+
+ pDestination = (uint16_t*)hgfx->FBStartAdress;
+ pDestination += x * hgfx->ImageHeight;
+ pDestination += y;
+
+ *(__IO uint16_t*)pDestination = 0xFF << 8 | color;
+}
+
+/* this is NOT fast nor optimized */
+void GFX_draw_circle(GFX_DrawCfgScreen *hgfx, point_t center, uint8_t radius, int8_t color)
+{
+ int x, y;
+ int l;
+ int r2, y2;
+ int y2_new;
+ int ty;
+
+ /* cos pi/4 = 185363 / 2^18 (approx) */
+ l = (radius * 185363) >> 18;
+
+ /* hw */
+ l += 1;
+
+ /* At x=0, y=radius */
+ y = radius;
+
+ r2 = y2 = y * y;
+ ty = (2 * y) - 1;
+ y2_new = r2 + 3;
+
+ for (x = 0; x <= l; x++) {
+ y2_new -= (2 * x) - 3;
+
+ if ((y2 - y2_new) >= ty) {
+ y2 -= ty;
+ y -= 1;
+ ty -= 2;
+ }
+
+ GFX_draw_pixel (hgfx, x + center.x, y + center.y, color);
+ GFX_draw_pixel (hgfx, x + center.x, -y + center.y, color);
+ GFX_draw_pixel (hgfx, -x + center.x, y + center.y, color);
+ GFX_draw_pixel (hgfx, -x + center.x, -y + center.y, color);
+
+ GFX_draw_pixel (hgfx, y + center.x, x + center.y, color);
+ GFX_draw_pixel (hgfx, y + center.x, -x + center.y, color);
+ GFX_draw_pixel (hgfx, -y + center.x, x + center.y, color);
+ GFX_draw_pixel (hgfx, -y + center.x, -x + center.y, color);
+ }
+}
+
+
+void GFX_draw_colorline(GFX_DrawCfgScreen *hgfx, point_t start, point_t stop, uint8_t color)
+{
+ uint32_t pDestination;
+ uint32_t j;
+ uint32_t temp;
+
+ if(start.x == stop.x)
+ {
+ if(stop.y < start.y)
+ {
+ temp = stop.y;
+ stop.y = start.y;
+ start.y = temp;
+ }
+ pDestination = (uint32_t)hgfx->FBStartAdress;
+ pDestination += start.x * hgfx->ImageHeight * 2;
+ pDestination += start.y * 2;
+ for (j = stop.y - start.y; j > 0; j--)
+ {
+ *(__IO uint8_t*)pDestination = color;
+ pDestination += 1;
+ *(__IO uint8_t*)pDestination = 0xFF;
+ pDestination += 1;
+ }
+ }
+ else
+ if(start.y == stop.y)
+ {
+ if(stop.x < start.x)
+ {
+ temp = stop.x;
+ stop.x = start.x;
+ start.x = temp;
+ }
+ pDestination = (uint32_t)hgfx->FBStartAdress;
+ pDestination += start.x * hgfx->ImageHeight * 2;
+ pDestination += start.y * 2;
+ for (j = stop.x - start.x; j > 0; j--)
+ {
+ *(__IO uint8_t*)pDestination = color;
+ pDestination += 1;
+ *(__IO uint8_t*)pDestination = 0xFF;
+ pDestination -= 1;
+ pDestination += hgfx->ImageHeight * 2;
+ }
+ }
+ else // diagonal Bresenham's_line_algorithm
+ {
+ int x0 = start.x;
+ int y0 = start.y;
+ int x1 = stop.x;
+ int y1 = stop.y;
+ int dx = abs(x1-x0), sx = x0dy ? dx : -dy)/2, e2;
+
+ for(;;)
+ {
+ pDestination = (uint32_t)hgfx->FBStartAdress;
+ pDestination += ((x0 * hgfx->ImageHeight) + y0) * 2;
+ *(__IO uint8_t*)pDestination = color;
+ pDestination += 1;
+ *(__IO uint8_t*)pDestination = 0xFF;
+ if (x0==x1 && y0==y1) break;
+ e2 = err;
+ if (e2 >-dx) { err -= dy; x0 += sx; }
+ if (e2 < dy) { err += dx; y0 += sy; }
+ }
+ }
+}
+
+// ===============================================================================
+// GFX_graph_print
+/// @brief Print all those nice curves, especially in logbook und miniLiveLogGraph
+/// @version 0.0.2 hw 160519
+///
+/// 151022 hw -bug fix
+/// - die aktuelle Version macht keine Linien mehr �ber die gesamte Bildschirmh�he.
+/// - daf�r sind L�cher in der Kurve (z.B. Temperaturgraph Tauchgang Matthias 17.10.15 15:19)
+///
+/// more details about range can be found in show_logbook_logbook_show_log_page2() - temperature graph
+///
+/// @param window: top and bottom is only the range used by the data of the graph, not the entire screen / scale
+/// @param drawVeilUntil: ist auff�llen des Bereichs unter der Kurve mit etwas hellerer Farbe
+/// @param Xdivide: wird bisher nichr benutzt.
+// ===============================================================================
+
+
+void GFX_graph_print(GFX_DrawCfgScreen *hgfx, const SWindowGimpStyle *window, const int16_t drawVeilUntil, uint8_t Xdivide, uint16_t dataMin, uint16_t dataMax, uint16_t *data, uint16_t datalength, uint8_t color, uint8_t *colour_data)
+{
+ uint16_t* pDestination_tmp;
+ uint16_t* pDestination_start;
+ uint16_t* pDestination_end;
+ uint16_t* pDestination_zero_veil;
+
+ uint32_t max = 0;
+ int windowheight = -1;
+ int windowwidth = -1;
+ int i = -1;
+ int w1 = -1;
+ int w2 = -1;
+
+ uint32_t h_ulong = 0;
+ uint32_t h_ulong_old = 0;
+ _Bool invert = 0;
+
+ uint16_t dataDelta = 0;
+ uint16_t dataDeltaHalve = 0;
+ uint16_t dataTemp = 0;
+
+ uint8_t colorDataTemp;
+ uint8_t colormask = 0;
+
+ pDestination_zero_veil = 0;
+
+ if(dataMin > dataMax)
+ {
+ uint16_t dataFlip;
+ dataFlip = dataMin;
+ dataMin = dataMax;
+ dataMax = dataFlip;
+ invert = 1;
+ }
+ else
+ invert = 0;
+
+ colormask = color;
+
+ if(window->bottom > 479)
+ return;
+ if(window->top > 479)
+ return;
+ if(window->right > 799)
+ return;
+ if(window->left > 799)
+ return;
+ if(window->bottom < 0)
+ return;
+ if(window->top < 0)
+ return;
+ if(window->right < 0)
+ return;
+ if(window->left < 0)
+ return;
+ if(window->bottom <= window->top)
+ return;
+ if(window->right <= window->left)
+ return;
+
+ windowheight = window->bottom - window->top ;
+ windowwidth = window->right - window->left;
+ w1 = 0;
+ w2 = 0;
+ if(dataMax == dataMin)
+ dataMax++;
+ dataDelta = (unsigned long)(dataMax - dataMin);
+ dataDeltaHalve = dataDelta / 2;
+ while((w1 <= windowwidth) && (w2 < datalength))
+ {
+ int tmp = (10 * w1 * (long)datalength)/windowwidth;
+ w2 = tmp/10;
+ int rest = tmp - w2*10;
+ if(rest >= 5)
+ w2++;
+
+ if((datalength - 1) < w2)
+ w2 = datalength-1;
+
+ if(colour_data != NULL)
+ {
+ colorDataTemp = colour_data[w2];
+ colormask = color + colorDataTemp;
+ }
+
+ dataTemp = data[w2];
+ if(Xdivide > 1)
+ {
+ w2++;
+ for(i=1;idataTemp)
+ dataTemp = data[w2];
+ w2++;
+ }
+ }
+
+ if(dataTemp > dataMin)
+ dataTemp -= dataMin;
+ else
+ dataTemp = 0;
+
+ if(invert)
+ {
+ if(dataTemp < dataDelta)
+ dataTemp = dataDelta - dataTemp;
+ else
+ dataTemp = 0;
+ }
+
+ h_ulong = (unsigned long)dataTemp;
+ h_ulong *= windowheight;
+ h_ulong += dataDeltaHalve;
+ h_ulong /= dataDelta;
+
+ if(h_ulong > (window->bottom - window->top))
+ h_ulong = (window->bottom - window->top);
+
+ if(drawVeilUntil > 0)
+ {
+ pDestination_zero_veil = (uint16_t*)hgfx->FBStartAdress;
+ pDestination_zero_veil += ((479 - (drawVeilUntil - 2) ) + ((w1 + window->left) * hgfx->ImageHeight) );
+ }
+ else if(drawVeilUntil < 0 )
+ {
+ pDestination_zero_veil = (uint16_t*)hgfx->FBStartAdress;
+ pDestination_zero_veil += ((479 + (drawVeilUntil)) + ((w1 + window->left) * hgfx->ImageHeight) );
+ }
+
+ if(h_ulong + window->top > max)
+ {
+ max = h_ulong + window->top;
+ }
+
+// hw 160519 wof�r ist das? Damit funktioniert Temperatur 25,5�C nicht!
+// if((dataMax == 255) || (data[w2] != 255))
+// {
+ //output_content[pointer] = colormask;
+ //output_mask[pointer] = true;
+ if(dataTemp != 0xFFFF) /* do not draw invalid data pixels */
+ {
+ if(w1 > 0)
+ {
+ pDestination_start = (uint16_t*)hgfx->FBStartAdress;
+ pDestination_start += (((479 - (window->top)) + ((w1 + window->left) * hgfx->ImageHeight)));
+ pDestination_end = pDestination_start;
+
+ if(h_ulong >= h_ulong_old)
+ {
+ pDestination_start -= h_ulong_old;
+ pDestination_end -= h_ulong;
+
+ }
+ else
+ {
+ if(h_ulong < h_ulong_old)
+ {
+ pDestination_start += h_ulong_old;
+ pDestination_end += h_ulong;
+ }
+ else
+ {
+ pDestination_start += h_ulong;
+ pDestination_end += h_ulong_old;
+ }
+ }
+
+
+ // deco stops
+ if(drawVeilUntil < 0)
+ {
+ pDestination_tmp = pDestination_end;
+ while(pDestination_tmp <= pDestination_zero_veil)
+ {
+ *(__IO uint16_t*)pDestination_tmp = (0x80 << 8) | colormask;
+ pDestination_tmp++;
+ }
+ }
+ else
+ {
+ // regular graph with veil underneath if requested
+ // von oben nach unten
+ // von grossen pDestination Werten zu kleinen pDestination Werten
+ {
+ pDestination_tmp = pDestination_start;
+ while(pDestination_tmp >= pDestination_end)
+ {
+ *(__IO uint16_t*)pDestination_tmp = (0xFF << 8) | colormask ;
+ pDestination_tmp--;
+ }
+ }
+
+ while((drawVeilUntil > 0) && (pDestination_tmp >= pDestination_zero_veil))
+ {
+ *(__IO uint16_t*)pDestination_tmp = (0x20 << 8) | colormask ;
+ pDestination_tmp--;
+ }
+ }
+ }
+ h_ulong_old = h_ulong;
+ }
+ w1++;
+ w2++;
+ }
+}
+
+
+void GFX_draw_header(GFX_DrawCfgScreen *hgfx, uint8_t colorId)
+{
+ uint32_t pDestination;
+ point_t start, stop, now;
+ uint8_t alpha;
+
+ /* display coordinate system */
+ start.y = 400;
+ stop.y = 479;
+
+ start.x = 0;
+ stop.x = 799;
+
+ now.y = start.y;
+ now.x = start.x;
+
+ while (now.x <= stop.x)
+ {
+ now.y = start.y;
+ pDestination = (uint32_t)hgfx->FBStartAdress;
+ pDestination += now.x * hgfx->ImageHeight * 2;
+ pDestination += now.y * 2;
+ now.x += 1;
+
+ alpha = 27;
+ while(alpha < 246)
+ {
+ alpha += 9;
+ *(__IO uint8_t*)pDestination = colorId;
+ pDestination += 1;
+ *(__IO uint8_t*)pDestination = alpha;
+ pDestination += 1;
+ now.y += 1;
+ }
+
+ while(now.y <= stop.y)
+ {
+ *(__IO uint8_t*)pDestination = colorId;
+ pDestination += 1;
+ *(__IO uint8_t*)pDestination = 0xFF;
+ pDestination += 1;
+ now.y += 1;
+ }
+ }
+}
+
+void GFX_draw_box2(GFX_DrawCfgScreen *hgfx, point_t start, point_t stop, uint8_t color, uint8_t roundCorners)
+{
+ point_t point2, point4;
+
+ if(roundCorners)
+ {
+ point2.x = stop.x - start.x;
+ point2.y = stop.y - start.y;
+ GFX_draw_box(hgfx,start,point2,1,color);
+ }
+ else
+ {
+ point2.x = stop.x;
+ point2.y = start.y;
+
+ point4.x = start.x;
+ point4.y = stop.y;
+
+ GFX_draw_line(hgfx,start,point2,color);
+ GFX_draw_line(hgfx,point2,stop,color);
+ GFX_draw_line(hgfx,stop,point4,color);
+ GFX_draw_line(hgfx,point4,start,color);
+ }
+}
+
+void GFX_draw_box(GFX_DrawCfgScreen *hgfx, point_t LeftLow, point_t WidthHeight, uint8_t Style, uint8_t color)
+{
+ uint16_t* pDestination;
+ uint16_t* pStart;
+ uint32_t j;
+ uint32_t lineWidth, lineHeight;
+ int x, y;
+ uint8_t intensity;
+ int stepdir;
+
+ typedef struct {
+ int x;
+ int y;
+ uint8_t intensity;
+ } corner_t;
+ const corner_t corner[16] = {
+ {3,3,255}, // nur einmal
+ {9,0,242},
+ {8,0,194},
+ {7,0,115},
+ {6,0,36},
+ {9,1,33},
+ {8,1,84},
+ {7,1,161},
+ {6,1,255},
+ {5,1,242},
+ {4,1,36},
+ {6,2,33},
+ {5,2,84},
+ {4,2,255},
+ {3,2,84},
+ {4,3,110}
+ };
+
+ lineWidth = WidthHeight.x;
+ lineHeight = WidthHeight.y;
+ pStart = (uint16_t*)hgfx->FBStartAdress;
+
+ pStart += LeftLow.x * hgfx->ImageHeight;
+ pStart += LeftLow.y;
+ stepdir = 1;
+
+ // Untere Linie
+ pDestination = pStart;
+ if(Style)
+ {
+ pDestination += stepdir * 10 * hgfx->ImageHeight;
+ lineWidth -= 18;
+ }
+ for (j = lineWidth; j > 0; j--)
+ {
+
+ *(__IO uint16_t*)pDestination = 0xFF00 + color;
+ pDestination += stepdir * hgfx->ImageHeight;
+ }
+
+ // Obere Linie
+
+ pDestination = pStart + stepdir * WidthHeight.y;
+ if(Style)
+ {
+ pDestination += stepdir * 10 * hgfx->ImageHeight;
+ }
+
+ for (j = lineWidth; j > 0; j--)
+ {
+ *(__IO uint16_t*)pDestination = 0xFF00 + color;
+ pDestination += stepdir * hgfx->ImageHeight;
+ }
+
+ // Linke Linie
+ pDestination = pStart;
+
+ if(Style)
+ {
+ pDestination += stepdir * 10;
+ lineHeight -= 18;
+ }
+
+ for (j = lineHeight; j > 0; j--)
+ {
+ *(__IO uint16_t*)pDestination = 0xFF00 + color;
+ pDestination += stepdir;
+ }
+
+
+ // Rechte Linie
+
+ pDestination = pStart + stepdir * WidthHeight.x * hgfx->ImageHeight;
+ if(Style)
+ {
+ pDestination += stepdir * 10;
+ }
+
+ for (j = lineHeight; j > 0; j--)
+ {
+ *(__IO uint16_t*)pDestination = 0xFF00 + color;
+ pDestination += stepdir;
+ }
+
+
+ // Ecken wenn notwendig == Style
+ if(Style)
+ {
+ // links unten
+ pDestination = pStart;
+ x = corner[0].x;
+ y = corner[0].y;
+ intensity = corner[0].intensity;
+
+ *(__IO uint16_t*)(pDestination + stepdir * (y + (x * hgfx->ImageHeight))) = (intensity << 8) + color;
+
+ for(j = 15; j > 0; j--)
+ {
+ x = corner[j].x;
+ y = corner[j].y;
+ intensity = corner[j].intensity;
+ *(__IO uint16_t*)(pDestination + stepdir * (y + (x * hgfx->ImageHeight))) = (intensity << 8) + color;
+ *(__IO uint16_t*)(pDestination + stepdir * (x + (y * hgfx->ImageHeight))) = (intensity << 8) + color;
+ }
+ // links oben
+ pDestination = pStart + stepdir * WidthHeight.y;
+ x = corner[0].x;
+ y = corner[0].y;
+ intensity = corner[0].intensity;
+ *(__IO uint16_t*)(pDestination + stepdir * (-y + (x * hgfx->ImageHeight))) = (intensity << 8) + color;
+
+ for(j = 15; j > 0; j--)
+ {
+ x = corner[j].x;
+ y = corner[j].y;
+ intensity = corner[j].intensity;
+ *(__IO uint16_t*)(pDestination + stepdir * (-y + (x * hgfx->ImageHeight))) = (intensity << 8) + color;
+ *(__IO uint16_t*)(pDestination + stepdir * (-x + (y * hgfx->ImageHeight))) = (intensity << 8) + color;
+ }
+ // rechts unten
+ pDestination = pStart + stepdir * WidthHeight.x * hgfx->ImageHeight;
+ x = corner[0].x;
+ y = corner[0].y;
+ intensity = corner[0].intensity;
+ *(__IO uint16_t*)(pDestination + stepdir * (y - (x * hgfx->ImageHeight))) = (intensity << 8) + color;
+
+ for(j = 15; j > 0; j--)
+ {
+ x = corner[j].x;
+ y = corner[j].y;
+ intensity = corner[j].intensity;
+ *(__IO uint16_t*)(pDestination + stepdir * (y - (x * hgfx->ImageHeight))) = (intensity << 8) + color;
+ *(__IO uint16_t*)(pDestination + stepdir * (x - (y * hgfx->ImageHeight))) = (intensity << 8) + color;
+ }
+ // rechts oben
+ pDestination = pStart + stepdir * WidthHeight.y + stepdir * WidthHeight.x * hgfx->ImageHeight;
+ x = corner[0].x;
+ y = corner[0].y;
+ intensity = corner[0].intensity;
+ *(__IO uint16_t*)(pDestination + stepdir * -1 * (y + (x * hgfx->ImageHeight))) = (intensity << 8) + color;
+
+ for(j = 15; j > 0; j--)
+ {
+ x = corner[j].x;
+ y = corner[j].y;
+ intensity = corner[j].intensity;
+ *(__IO uint16_t*)(pDestination + stepdir * -1 * (y + (x * hgfx->ImageHeight))) = (intensity << 8) + color;
+ *(__IO uint16_t*)(pDestination + stepdir * -1 * (x + (y * hgfx->ImageHeight))) = (intensity << 8) + color;
+ }
+ }
+}
+
+
+/**
+ ******************************************************************************
+ * @brief GFX write label. / Write string with defined color
+ * @author heinrichs weikamp gmbh
+ * @version V0.0.1
+ * @date 07-July-2014
+ ******************************************************************************
+ *
+ * @param hgfx: check gfx_engine.h.
+ * @param color: 16bit Alpha+CLUT.
+ * @retval None
+ */
+
+uint32_t GFX_write_label(const tFont *Font, GFX_DrawCfgWindow* hgfx, const char *pText, uint8_t color)
+{
+ return GFX_write_string_color(Font, hgfx, pText, 0, color);
+}
+
+
+/**
+ ******************************************************************************
+ * @brief GFX writeGfx_write_label_varstring. / Write string with all parameters and font color options
+ heinrichs weikamp gmbh
+ * @version V0.0.1
+ * @date 22-April-2014
+ ******************************************************************************
+ *
+ * @param XleftGimpStyle:
+ * @param XrightGimpStyle:
+ * @param YtopGimpStyle:
+ * @param color:
+ * @param tFont:
+ * @param text: text to be printed
+ * @retval None
+ */
+
+void Gfx_write_label_var(GFX_DrawCfgScreen *screenInput, uint16_t XleftGimpStyle, uint16_t XrightGimpStyle, uint16_t YtopGimpStyle, const tFont *Font, const uint8_t color, const char *text)
+{
+
+ GFX_DrawCfgWindow hgfx;
+
+ if(XrightGimpStyle > 799)
+ XrightGimpStyle = 799;
+ if(XleftGimpStyle >= XrightGimpStyle)
+ XleftGimpStyle = 0;
+ if(YtopGimpStyle > 479)
+ YtopGimpStyle = 479;
+ hgfx.Image = screenInput;
+ hgfx.WindowNumberOfTextLines = 1;
+ hgfx.WindowLineSpacing = 0;
+ hgfx.WindowTab = 0;
+
+ hgfx.WindowX0 = XleftGimpStyle;
+ hgfx.WindowX1 = XrightGimpStyle;
+ hgfx.WindowY1 = 479 - YtopGimpStyle;
+ if(hgfx.WindowY1 < Font->height)
+ hgfx.WindowY0 = 0;
+ else
+ hgfx.WindowY0 = hgfx.WindowY1 - Font->height;
+ GFX_write_label(Font, &hgfx, text, color);
+}
+
+/**
+ ******************************************************************************
+ * @brief GFX write string. / Write string with all parameters and font options
+ * @author heinrichs weikamp gmbh
+ * @version V0.0.1
+ * @date 22-April-2014
+ ******************************************************************************
+ *
+ * @param hgfx: check gfx_engine.h.
+ * @param color: 32bit ARGB8888.
+ * @retval None
+ */
+
+uint16_t GFX_return_offset(const tFont *Font, char *pText, uint8_t position)
+{
+ char character;
+ uint16_t digit, i;
+ uint8_t found;
+ uint16_t distance;
+
+ if(position == 0)
+ return 0;
+
+ distance = 0;
+ for(digit = 0; digit < position; digit++)
+ {
+ character = pText[digit];
+ if(character == 0)
+ return 0;
+
+ found = 0;
+ for(i=0;ilength;i++)
+ {
+ if(Font->chars[i].code == character)
+ {
+ found = 1;
+ break;
+ }
+ }
+ if(found)
+ {
+ distance += (uint16_t)(Font->chars[i].image->width);
+ if(Font == &FontT144)
+ distance += 3;
+ else
+ if(Font == &FontT105)
+ distance += 2;
+ }
+ }
+ return distance;
+
+ /* FEHLT:
+ if(*pText < ' ')
+ if((*pText) & 0x80)
+
+ if(((tFont *)settings.font == &FontT105) && settings.dualFont && ((*pText == '.') || (*pText == ':')))
+ settings.font = (uint32_t)&FontT54;
+ */
+}
+
+void GFX_clean_line(GFX_DrawCfgWindow* hgfx, uint32_t line_number)
+{
+ uint16_t height;
+ uint32_t pDestination, i, j;
+ uint16_t left, width, bottom, nextlineStep;
+
+ bottom = hgfx->WindowY0;
+
+ if(hgfx->WindowNumberOfTextLines && line_number && (line_number <= hgfx->WindowNumberOfTextLines))
+ {
+ bottom += hgfx->WindowLineSpacing * (hgfx->WindowNumberOfTextLines - line_number);
+ height = hgfx->WindowLineSpacing;
+ }
+ else
+ {
+ height = 1 + hgfx->WindowY1 - bottom;
+ }
+
+ pDestination = (uint32_t)hgfx->Image->FBStartAdress;
+
+ left = hgfx->WindowX0;
+ width = 1 + hgfx->WindowX1 - left;
+ nextlineStep = hgfx->Image->ImageHeight - height;
+ nextlineStep *= 2;
+ pDestination += 2 * bottom;
+ pDestination += 2 * hgfx->Image->ImageHeight * left;
+
+ for(j = width; j > 0; j--)
+ {
+ for(i = height; i > 0; i--)
+ {
+ *(__IO uint16_t*)pDestination = 0;
+ pDestination += 2;
+ }
+ pDestination += nextlineStep;
+ }
+}
+
+
+void GFX_clean_area(GFX_DrawCfgScreen *tMscreen, uint16_t XleftGimpStyle, uint16_t XrightGimpStyle, uint16_t YtopGimpStyle, uint16_t YBottomGimpStyle)
+{
+ uint16_t height;
+ uint32_t pDestination, i, j;
+ int32_t left, width, bottom, nextlineStep;
+
+ bottom = tMscreen->ImageHeight - YBottomGimpStyle;
+ height = 1 + YBottomGimpStyle - YtopGimpStyle;
+
+ if(bottom < 0)
+ bottom = 0;
+ if(height > tMscreen->ImageHeight)
+ height = tMscreen->ImageHeight;
+
+ pDestination = tMscreen->FBStartAdress;
+
+ left = XleftGimpStyle;
+ width = 1 + XrightGimpStyle - left;
+ if(width < 1)
+ width = 1;
+
+ if(width > tMscreen->ImageWidth)
+ width = tMscreen->ImageWidth;
+
+ nextlineStep = tMscreen->ImageHeight - height;
+ nextlineStep *= 2;
+ pDestination += 2 * bottom;
+ pDestination += 2 * tMscreen->ImageHeight * left;
+
+ for(j = width; j > 0; j--)
+ {
+ for(i = height; i > 0; i--)
+ {
+ *(__IO uint16_t*)pDestination = 0;
+ pDestination += 2;
+ }
+ pDestination += nextlineStep;
+ }
+}
+
+
+uint32_t GFX_write_string(const tFont *Font, GFX_DrawCfgWindow* hgfx, const char *pText, uint32_t line_number)
+{
+ return GFX_write_string_color(Font, hgfx, pText, line_number, 0);
+}
+
+uint32_t GFX_write_string_color(const tFont *Font, GFX_DrawCfgWindow* hgfx, const char *pText, uint32_t line_number, uint8_t color)
+{
+ if(hgfx->Image->FBStartAdress < FBGlobalStart)
+ return 0;
+
+ GFX_CfgWriteString settings;
+ uint32_t newXdelta;
+ uint8_t minimal = 0;
+// uint32_t try_again;
+
+ if(hgfx->WindowNumberOfTextLines && line_number && (line_number <= hgfx->WindowNumberOfTextLines))
+ {
+ settings.Ydelta = hgfx->WindowLineSpacing * (hgfx->WindowNumberOfTextLines - line_number);
+ }
+ else
+ {
+ settings.Ydelta = 0;
+ }
+ settings.font = (uint32_t)Font;
+ settings.Xdelta = 0;
+ settings.color = color;
+ settings.invert = 0;
+ settings.resize = 0;
+ settings.dualFont = 0;
+ settings.spaceMode = 0;
+ settings.singleSpaceWithSizeOfNextChar = 0;
+ settings.useTinyFont = 0;
+ settings.TinyFontExtraYdelta = 0;
+ settings.TinyFont = (uint32_t)Font;
+ settings.doubleSize = 0;
+
+ if((*pText) == TXT_MINIMAL) // for customtext and anything with Sonderzeichen
+ minimal = 1;
+ else
+ minimal = 0;
+
+ if(Font == &FontT144)
+ {
+ settings.TinyFont = (uint32_t)&FontT84;
+ settings.Ydelta = 12;
+ }
+ else
+ if(Font == &FontT105)
+ settings.TinyFont = (uint32_t)&FontT54;
+ else
+ if(Font == &FontT54)
+ {
+ settings.TinyFont = (uint32_t)&FontT48;
+ settings.TinyFontExtraYdelta = -9;
+ }
+ else
+ if(Font == &FontT48)
+ {
+ settings.TinyFont = (uint32_t)&FontT24;
+ settings.TinyFontExtraYdelta = 6;
+ }
+ else
+ if(Font == &FontT42)
+ {
+ settings.TinyFont = (uint32_t)&FontT24;
+ settings.TinyFontExtraYdelta = 2;
+ }
+
+ settings.actualFont = (tFont *)settings.font;
+
+ while ((*pText != 0) && (settings.Xdelta != 0x0000FFFF))// und fehlend: Abfrage window / image size
+ {
+// try_again = 0;
+
+ if((*pText == '\177') && !minimal)
+ {
+ if(settings.singleSpaceWithSizeOfNextChar)
+ {
+ settings.singleSpaceWithSizeOfNextChar = 0;
+ pText++;
+ settings.Xdelta += *pText;
+ }
+ else
+ settings.singleSpaceWithSizeOfNextChar = 1;
+ }
+ else
+ if(*pText < ' ')
+ {
+ /* Xdelta -inline- changes */
+ if((*pText == '\t') && !minimal)
+ settings.Xdelta = hgfx->WindowTab - hgfx->WindowX0;
+ else
+ if(*pText == '\r') // carriage return, no newline
+ settings.Xdelta = 0;
+ else
+ if((*pText == '\001')) // center
+ settings.Xdelta = GFX_write__Modify_Xdelta__Centered(&settings, hgfx, pText+1);
+ else
+ if((*pText == '\002')) // right
+ settings.Xdelta = GFX_write__Modify_Xdelta__RightAlign(&settings, hgfx, pText+1);
+ else
+ if((*pText == '\003') && !minimal) // doubleSize
+ settings.doubleSize = 1;
+ else
+ /* Xdelta -up/down changes */
+ if((*pText == '\f') && !minimal) // form feed = top align
+ {
+ if((hgfx->WindowY1 - hgfx->WindowY0) >= ((tFont *)settings.font)->height)
+ {
+ settings.Ydelta = hgfx->WindowY1 - hgfx->WindowY0;
+ settings.Ydelta -= ((tFont *)settings.font)->height;
+ }
+ }
+ else
+ if(*pText == '\n') // newline, no carriage return
+ {
+ if(hgfx->WindowNumberOfTextLines && (line_number < hgfx->WindowNumberOfTextLines))
+ {
+ line_number++;
+ settings.Ydelta = hgfx->WindowLineSpacing * (hgfx->WindowNumberOfTextLines - line_number);
+ }
+ }
+ else
+ /* Font style changes */
+ if(*pText == '\a')
+ settings.invert = settings.invert ? 0 : 1;
+ else
+ if((*pText == '\016') && !minimal)
+ {
+ if(settings.dualFont == 0)
+ settings.dualFont = 1;
+ else
+ settings.actualFont = (tFont *)settings.TinyFont;
+ }
+ else
+ if((*pText == '\017') && !minimal)
+ {
+ settings.dualFont = 0;
+ settings.actualFont = (tFont *)settings.font;
+ }
+ else
+ if((*pText >= '\020') && (*pText <= '\032') && !minimal)
+ settings.color = *pText - '\020';
+ else
+ if((*pText == '\034') && !minimal)
+ settings.spaceMode = 1;
+ else
+ if((*pText == '\035') && !minimal)
+ settings.spaceMode = 0;
+ }
+ else
+ if(((*pText) == TXT_2BYTE) && !minimal)
+ {
+ pText++;
+ settings.Xdelta = GFX_write_substring(&settings, hgfx, (uint8_t)TXT_2BYTE, (int8_t)*pText);
+ }
+ else
+ if(((*pText) & 0x80) && !minimal)
+ settings.Xdelta = GFX_write_substring(&settings, hgfx, (uint8_t)*pText, 0);
+ else
+ if(!settings.invert && (*pText == ' '))
+ {
+ if(settings.spaceMode == 0)
+ settings.Xdelta += ((tFont *)settings.font)->spacesize;
+ else
+ settings.Xdelta += ((tFont *)settings.font)->spacesize2Monospaced;
+ }
+ else
+ if((settings.spaceMode == 1) && (*pText == ' '))
+ settings.Xdelta += ((tFont *)settings.font)->spacesize2Monospaced;
+ else
+ {
+ if(((tFont *)settings.font == &FontT144) && ((*pText == '.') || (*pText == ':')))
+ settings.actualFont = (tFont *)settings.TinyFont;
+ else
+ if(((tFont *)settings.font == &FontT105) && settings.dualFont && ((*pText == '.') || (*pText == ':')))
+ settings.actualFont = (tFont *)settings.TinyFont;
+
+ if(settings.actualFont == (tFont *)settings.TinyFont)
+ settings.Ydelta += settings.TinyFontExtraYdelta;
+
+ newXdelta = GFX_write_char(hgfx, &settings, *(uint8_t *)pText, settings.actualFont);
+ settings.Xdelta = newXdelta;
+
+ if(settings.actualFont == (tFont *)settings.TinyFont)
+ settings.Ydelta -= settings.TinyFontExtraYdelta;
+ }
+ if(pText != 0) /* for TXT_2BYTE */
+ pText++;
+ }
+ return settings.Ydelta;
+}
+
+/* Private functions ---------------------------------------------------------*/
+/******************************************************************************
+ Static Function
+*******************************************************************************/
+
+/**
+ ******************************************************************************
+ * @brief GFX write substring. / Write string without parameters
+ * @author heinrichs weikamp gmbh
+ * @version V0.0.1
+ * @date 22-April-2014
+ ******************************************************************************
+ *
+ * @param hgfx: check gfx_engine.h.
+ * @param color: 32bit ARGB8888.
+ * @retval None
+ */
+
+static uint32_t GFX_write_substring(GFX_CfgWriteString* cfg, GFX_DrawCfgWindow* hgfx, uint8_t textId, int8_t nextCharFor2Byte)
+{
+ uint8_t i, j;
+ uint32_t found;
+ uint32_t pText;
+ uint16_t decodeUTF8;
+
+// -----------------------------
+ if(textId != (uint8_t)TXT_2BYTE)
+ {
+ found = 0;
+ j = 0;
+ for(i=(uint8_t)TXT_Language;i<(uint8_t)TXT_END;i++)
+ {
+ j++;
+ }
+ if(!found)
+ return cfg->Xdelta;
+
+ }
+// -----------------------------
+ else
+ {
+ if(!nextCharFor2Byte)
+ return cfg->Xdelta;
+
+ found = 0;
+
+ if(!found)
+ return cfg->Xdelta;
+ }
+// -----------------------------
+
+ if(cfg->actualFont == (tFont *)cfg->TinyFont)
+ cfg->Ydelta += cfg->TinyFontExtraYdelta;
+
+ while (*(char*)pText != 0)// und fehlend: Abfrage window / image size
+ {
+ if(*(char*)pText == '\t')
+ cfg->Xdelta = hgfx->WindowTab - hgfx->WindowX0;
+ else
+ if((*(char*)pText == ' ') && (cfg->invert == 0)) /* bypass drawing of white space only for not inverted mode */
+ {
+ cfg->Xdelta += ((tFont *)cfg->actualFont)->spacesize;
+ }
+ else
+ if((*(char*)pText) & 0x80) /* Identify a UNICODE character other than standard ASCII using the highest bit */
+ {
+ decodeUTF8 = ((*(char*)pText) & 0x1F) << 6; /* use 5bits of first byte for upper part of unicode */
+ pText++;
+ decodeUTF8 |= (*(char*)pText) & 0x3F; /* add lower 6bits as second part of the unicode */
+ if (decodeUTF8 <= 0xff) /* The following function has a uint8 input parameter ==> no UNICODEs > 0xff supported */
+ {
+ cfg->Xdelta = GFX_write_char(hgfx, cfg, (uint8_t)decodeUTF8, (tFont *)cfg->actualFont);
+ }
+ }
+ else
+ cfg->Xdelta = GFX_write_char(hgfx, cfg, *(uint8_t *)pText, (tFont *)cfg->actualFont);
+
+ pText++;
+ }
+
+ if(cfg->actualFont == (tFont *)cfg->TinyFont)
+ cfg->Ydelta -= cfg->TinyFontExtraYdelta;
+
+ return cfg->Xdelta;
+}
+
+
+/**
+ ******************************************************************************
+ * @brief GFX write char. / Write non-inverted, non-colored with entire 8 bit range
+ * @author heinrichs weikamp gmbh
+ * @version V0.0.1
+ * @date 22-April-2014
+ ******************************************************************************
+ *
+ * @param hgfx: check gfx_engine.h.
+ * @param Ydelta: input
+ * @param character: character
+ * @param *Font: pointer to font to be used for this char
+ * @retval Ydelta: 0x0000FFFF if not successful or char_truncated
+ */
+
+static uint32_t GFX_write_char_doubleSize(GFX_DrawCfgWindow* hgfx, GFX_CfgWriteString* cfg, uint8_t character, tFont *Font)
+{
+ uint32_t i, j;
+ uint32_t width, height;
+ uint32_t found;
+ uint16_t* pDestination;
+ uint32_t pSource;
+ uint32_t OffsetDestination;
+ uint32_t width_left;
+ uint32_t height_left;
+ uint32_t char_truncated_WidthFlag;
+ uint32_t char_truncated_Height;
+ uint8_t fill;
+ uint32_t widthFont, heightFont;
+ uint32_t nextLine;
+ int32_t stepdir;
+
+ stepdir = 1;
+
+ if(hgfx->Image->ImageWidth <= (hgfx->WindowX0 + cfg->Xdelta))
+ return 0x0000FFFF;
+
+ // -----------------------------
+ found = 0;
+ for(i=0;ilength;i++)
+ {
+ if(Font->chars[i].code == character)
+ {
+ found = 1;
+ break;
+ }
+ }
+ if(!found)
+ return cfg->Xdelta;
+
+ pSource = ((uint32_t)Font->chars[i].image->data);
+ pDestination = (uint16_t*)(hgfx->Image->FBStartAdress);
+
+ heightFont = Font->chars[i].image->height;
+ widthFont = Font->chars[i].image->width;
+
+ height = heightFont*2;
+ width = widthFont*2;
+
+
+ pDestination += (uint32_t)(hgfx->WindowX0 + cfg->Xdelta) * hgfx->Image->ImageHeight; /* set pointer to delta row */
+ pDestination += (hgfx->WindowY0 + cfg->Ydelta); /* set pointer to delta colum */
+
+ OffsetDestination = (hgfx->Image->ImageHeight - height);
+ nextLine = hgfx->Image->ImageHeight;
+
+// -----------------------------
+ char_truncated_WidthFlag = 0;
+ width_left = hgfx->Image->ImageWidth - (hgfx->WindowX0 + cfg->Xdelta);
+ if(width_left < width)
+ {
+ char_truncated_WidthFlag = 1;
+ width = width_left;
+ widthFont = width/2;
+ }
+// -----------------------------
+
+ char_truncated_Height = 0;
+ height_left = hgfx->Image->ImageHeight - (hgfx->WindowY0 + cfg->Ydelta);
+ if(height_left < height)
+ {
+ char_truncated_Height = height - height_left;
+ if((char_truncated_Height & 1) != 0)
+ {
+ height_left -= 1;
+ char_truncated_Height += 1;
+ }
+ height = height_left;
+ heightFont = height/2;
+ }
+
+ OffsetDestination += char_truncated_Height;
+// -----------------------------
+ if(height == 0)
+ return 0x0000FFFF;
+// -----------------------------
+
+ if(cfg->singleSpaceWithSizeOfNextChar)
+ {
+ cfg->singleSpaceWithSizeOfNextChar = 0;
+
+ if(cfg->invert)
+ fill = 0xFF;
+ else
+ fill = 0;
+
+ height /= 2;
+ for(i = width; i > 0; i--)
+ {
+ for (j = height; j > 0; j--)
+ {
+ *(__IO uint16_t*)pDestination = fill << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = fill << 8 | cfg->color;
+ pDestination += stepdir;
+ }
+ pDestination += stepdir * OffsetDestination;
+ }
+ }
+ else
+ if(cfg->invert)
+ {
+ if((heightFont & 3) == 0) /* unroll for perfomance, by 4 if possible, by 2 (16bit) otherwise */
+ {
+ heightFont /= 4;
+ for(i = widthFont; i > 0; i--)
+ {
+ if(*(uint8_t*)pSource != 0x01)
+ {
+ for (j = heightFont; j > 0; j--)
+ {
+ *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + nextLine) = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + nextLine) = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
+ pDestination += stepdir;
+ pSource++;
+
+ *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + nextLine) = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + nextLine) = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
+ pDestination += stepdir;
+ pSource++;
+
+ *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + nextLine) = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + nextLine) = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
+ pDestination += stepdir;
+ pSource++;
+
+ *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + nextLine) = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + nextLine) = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
+ pDestination += stepdir;
+ pSource++;
+ }
+ pSource += char_truncated_Height;
+ }
+ else
+ {
+ pSource++;
+ for (j = heightFont; j > 0; j--)
+ {
+ *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + nextLine) = 0xFF << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + nextLine) = 0xFF << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + nextLine) = 0xFF << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + nextLine) = 0xFF << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + nextLine) = 0xFF << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + nextLine) = 0xFF << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + nextLine) = 0xFF << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + nextLine) = 0xFF << 8 | cfg->color;
+ pDestination += stepdir;
+ }
+ }
+ pDestination += (OffsetDestination + nextLine) * stepdir;
+ }
+ }
+ else
+ {
+ heightFont /= 2;
+ for(i = widthFont; i > 0; i--)
+ {
+ if(*(uint8_t*)pSource != 0x01)
+ {
+ for (j = heightFont; j > 0; j--)
+ {
+ *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + nextLine) = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + nextLine) = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
+ pDestination += stepdir;
+ pSource++;
+
+ *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + nextLine) = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + nextLine) = (0xFF - *(uint8_t*)pSource) << 8 | cfg->color;
+ pDestination += stepdir;
+ pSource++;
+ }
+ pSource += char_truncated_Height;
+ }
+ else
+ {
+ pSource++;
+ for (j = heightFont; j > 0; j--)
+ {
+ *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + nextLine) = 0xFF << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + nextLine) = 0xFF << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + nextLine) = 0xFF << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + nextLine) = 0xFF << 8 | cfg->color;
+ pDestination += stepdir;
+ }
+ }
+ pDestination += (OffsetDestination + nextLine) * stepdir;
+ }
+ }
+ } /* inverted */
+ else
+ {
+ if((heightFont & 3) == 0) /* unroll for perfomance, by 4 if possible, by 2 (16bit) otherwise */
+ {
+ heightFont /= 4;
+ for(i = widthFont; i > 0; i--)
+ {
+ if(*(uint8_t*)pSource != 0x01)
+ {
+ for (j = heightFont; j > 0; j--)
+ {
+ *(__IO uint16_t*)pDestination = *(uint8_t*)pSource << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + (stepdir * nextLine)) = *(uint8_t*)pSource << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = *(uint8_t*)pSource << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + (stepdir * nextLine)) = *(uint8_t*)pSource << 8 | cfg->color;
+ pDestination += stepdir;
+ pSource++;
+
+ *(__IO uint16_t*)pDestination = *(uint8_t*)pSource << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + (stepdir * nextLine)) = *(uint8_t*)pSource << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = *(uint8_t*)pSource << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + (stepdir * nextLine)) = *(uint8_t*)pSource << 8 | cfg->color;
+ pDestination += stepdir;
+ pSource++;
+
+ *(__IO uint16_t*)pDestination = *(uint8_t*)pSource << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + (stepdir * nextLine)) = *(uint8_t*)pSource << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = *(uint8_t*)pSource << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + (stepdir * nextLine)) = *(uint8_t*)pSource << 8 | cfg->color;
+ pDestination += stepdir;
+ pSource++;
+
+ *(__IO uint16_t*)pDestination = *(uint8_t*)pSource << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + (stepdir * nextLine)) = *(uint8_t*)pSource << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = *(uint8_t*)pSource << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + (stepdir * nextLine)) = *(uint8_t*)pSource << 8 | cfg->color;
+ pDestination += stepdir;
+ pSource++;
+ }
+ pSource += char_truncated_Height;
+ }
+ else
+ {
+ pSource++;
+ pDestination += stepdir * height;
+ }
+ pDestination += stepdir * (OffsetDestination + nextLine);
+ }
+ }
+ else
+ {
+ heightFont /= 2;
+ for(i = widthFont; i > 0; i--)
+ {
+ if(*(uint8_t*)pSource != 0x01)
+ {
+ for (j = heightFont; j > 0; j--)
+ {
+ *(__IO uint16_t*)pDestination = *(uint8_t*)pSource << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + (stepdir * nextLine)) = *(uint8_t*)pSource << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = *(uint8_t*)pSource << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + (stepdir * nextLine)) = *(uint8_t*)pSource << 8 | cfg->color;
+ pDestination += stepdir;
+ pSource++;
+
+ *(__IO uint16_t*)pDestination = *(uint8_t*)pSource << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + (stepdir * nextLine)) = *(uint8_t*)pSource << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = *(uint8_t*)pSource << 8 | cfg->color;
+ *(__IO uint16_t*)(pDestination + (stepdir * nextLine)) = *(uint8_t*)pSource << 8 | cfg->color;
+ pDestination += stepdir;
+ pSource++;
+ }
+ pSource += char_truncated_Height;
+ }
+ else
+ {
+ pSource++;
+ pDestination += stepdir * height;
+ }
+ pDestination += stepdir * (OffsetDestination + nextLine);
+ }
+ }
+ }
+
+// -----------------------------
+
+ if(Font == &FontT144)
+ width += 6;
+ else
+ if(Font == &FontT105)
+ width += 4;
+
+// -----------------------------
+
+ if(char_truncated_WidthFlag)
+ return 0x0000FFFF;
+ else
+ return cfg->Xdelta + width;
+
+}
+
+
+/**
+ ******************************************************************************
+ * @brief GFX write char. / Write non-inverted, non-colored with entire 8 bit range
+ * @author heinrichs weikamp gmbh
+ * @version V0.0.1
+ * @date 22-April-2014
+ ******************************************************************************
+ *
+ * @param hgfx: check gfx_engine.h.
+ * @param Ydelta: input
+ * @param character: character
+ * @param *Font: pointer to font to be used for this char
+ * @retval Ydelta: 0x0000FFFF if not successful or char_truncated
+ */
+
+static uint32_t GFX_write_char(GFX_DrawCfgWindow* hgfx, GFX_CfgWriteString* cfg, uint8_t character, tFont *Font)
+{
+ if(cfg->doubleSize)
+ {
+ return GFX_write_char_doubleSize(hgfx, cfg, character, Font);
+ }
+
+ uint32_t i, j;
+ uint32_t width, height;
+ uint32_t found;
+ uint16_t* pDestination;
+ uint32_t pSource;
+ uint32_t OffsetDestination;
+ uint32_t width_left;
+ uint32_t height_left;
+ uint32_t char_truncated_WidthFlag;
+ uint32_t char_truncated_Height;
+ uint8_t fill;
+ uint32_t fillpattern;
+ int16_t stepdir;
+
+ stepdir = 1;
+
+ if(hgfx->Image->ImageWidth <= (hgfx->WindowX0 + cfg->Xdelta))
+ return 0x0000FFFF;
+
+ // -----------------------------
+ found = 0;
+ for(i=0;ilength;i++)
+ {
+ if(Font->chars[i].code == character)
+ {
+ found = 1;
+ break;
+ }
+ }
+ if(!found)
+ return cfg->Xdelta;
+// -----------------------------
+/*
+ if(Font == &Font144)
+ cfg->Xdelta += 3;
+ else
+ if(Font == &Font84)
+ cfg->Xdelta += 2;
+*/
+// -----------------------------
+
+
+ pSource = ((uint32_t)Font->chars[i].image->data);
+ pDestination = (uint16_t*)(hgfx->Image->FBStartAdress);
+
+
+ height = Font->chars[i].image->height;
+ width = Font->chars[i].image->width;
+
+ OffsetDestination = hgfx->Image->ImageHeight - height;
+
+
+ /* Xyyyyy y= height */
+ /* Xyyyyy x= width */
+ /* Xyyyyy */
+
+ pDestination += (hgfx->WindowX0 + cfg->Xdelta) * hgfx->Image->ImageHeight; /* set pointer to delta row */
+ pDestination += (hgfx->WindowY0 + cfg->Ydelta); /* set pointer to delta colum */
+
+// -----------------------------
+ char_truncated_WidthFlag = 0;
+ width_left = hgfx->Image->ImageWidth - (hgfx->WindowX0 + cfg->Xdelta);
+ if(width_left < width)
+ {
+ char_truncated_WidthFlag = 1;
+ width = width_left;
+ }
+// -----------------------------
+ char_truncated_Height = 0;
+ height_left = hgfx->Image->ImageHeight - (hgfx->WindowY0 + cfg->Ydelta);
+ if(height_left < height)
+ {
+ char_truncated_Height = height - height_left;
+ if((char_truncated_Height & 1) != 0)
+ {
+ height_left -= 1;
+ char_truncated_Height += 1;
+ }
+ height = height_left;
+ }
+ OffsetDestination += char_truncated_Height;
+// -----------------------------
+ if(height == 0)
+ return 0x0000FFFF;
+// -----------------------------
+
+ if(cfg->singleSpaceWithSizeOfNextChar)
+ {
+ cfg->singleSpaceWithSizeOfNextChar = 0;
+
+ if(cfg->invert)
+ fill = 0xFF;
+ else
+ fill = 0;
+
+ height /= 2;
+ for(i = width; i > 0; i--)
+ {
+ for (j = height; j > 0; j--)
+ {
+ *(__IO uint16_t*)pDestination = fill << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = fill << 8 | cfg->color;
+ pDestination += stepdir;
+ }
+ pDestination += stepdir * OffsetDestination;
+ }
+ }
+ else
+ if(cfg->invert)
+ {
+ if((height & 3) == 0) /* unroll for perfomance, by 4 if possible, by 2 (16bit) otherwise */
+ {
+ height /= 4;
+ for(i = width; i > 0; i--)
+ {
+ if(*(uint8_t*)pSource != 0x01)
+ {
+
+ for (j = height; j > 0; j--)
+ {
+ *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource++) << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource++) << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource++) << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource++) << 8 | cfg->color;
+ pDestination += stepdir;
+ }
+ pSource += char_truncated_Height;
+ }
+ else /* empty line => fast fill */
+ {
+ pSource++;
+ fillpattern = (( 0xFF << 8 | cfg->color) << 16) | ( 0xFF << 8 | cfg->color);
+ for (j = height; j > 0; j--)
+ {
+ *(__IO uint32_t*)pDestination = fillpattern;
+ pDestination += stepdir;
+ pDestination += stepdir;
+ *(__IO uint32_t*)pDestination = fillpattern;
+ pDestination += stepdir;
+ pDestination += stepdir;
+ }
+ }
+ pDestination += stepdir * OffsetDestination;
+ }
+ }
+ else
+ {
+ height /= 2;
+ for(i = width; i > 0; i--)
+ {
+ if(*(uint8_t*)pSource != 0x01)
+ {
+ for (j = height; j > 0; j--)
+ {
+ *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource++) << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = (0xFF - *(uint8_t*)pSource++) << 8 | cfg->color;
+ pDestination += stepdir;
+ }
+ pSource += char_truncated_Height;
+ }
+ else
+ {
+ pSource++;
+ for (j = height; j > 0; j--)
+ {
+ *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = 0xFF << 8 | cfg->color;
+ pDestination += stepdir;
+ }
+ }
+ pDestination += stepdir * OffsetDestination;
+ }
+ }
+ }
+ else /* not inverted */
+ {
+ if((height & 3) == 0) /* unroll for perfomance, by 4 if possible, by 2 (16bit) otherwise */
+ {
+
+ height /= 4;
+
+ for(i = width; i > 0; i--)
+ {
+ if(*(uint8_t*)pSource != 0x01)
+ {
+ for (j = height; j > 0; j--)
+ {
+ *(__IO uint16_t*)pDestination = ( *(uint8_t*)pSource++ << 8) | (cfg->color);
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = ( *(uint8_t*)pSource++ << 8) | (cfg->color);
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = ( *(uint8_t*)pSource++ << 8) | (cfg->color);
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = ( *(uint8_t*)pSource++ << 8) | (cfg->color);
+ pDestination += stepdir;
+ }
+
+ pSource += char_truncated_Height;
+ }
+ else /* clear line */
+ {
+ pSource++;
+ fillpattern = (cfg->color << 16) | cfg->color;
+
+ for (j = height; j > 0; j--)
+ {
+ *(__IO uint32_t*)pDestination = fillpattern;
+ pDestination += stepdir;
+ pDestination += stepdir;
+ *(__IO uint32_t*)pDestination = fillpattern;
+ pDestination += stepdir;
+ pDestination += stepdir;
+ }
+ }
+ pDestination += stepdir * OffsetDestination;
+ }
+ }
+ else
+ {
+ height /= 2;
+ for(i = width; i > 0; i--)
+ {
+ if(*(uint8_t*)pSource != 0x01)
+ {
+ for (j = height; j > 0; j--)
+ {
+ *(__IO uint16_t*)pDestination = ( *(uint8_t*)pSource++ << 8) | (cfg->color);
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = ( *(uint8_t*)pSource++ << 8) | (cfg->color);
+ pDestination += stepdir;
+ }
+ pSource += char_truncated_Height;
+ }
+ else /* clear line */
+ {
+ pSource++;
+ for (j = height; j > 0; j--)
+ {
+ *(__IO uint16_t*)pDestination = cfg->color;
+ pDestination += stepdir;
+ *(__IO uint16_t*)pDestination = cfg->color;
+ pDestination += stepdir;
+ }
+ }
+ pDestination += stepdir * OffsetDestination;
+ }
+ }
+ }
+
+// -----------------------------
+
+ if(Font == &FontT144)
+ width += 3;
+ else
+ if(Font == &FontT105)
+ width += 2;
+/*
+ else
+ if(Font == &Font144)
+ width += 3;
+ else
+ if(Font == &Font84)
+ width += 1;
+*/
+// -----------------------------
+
+ if(char_truncated_WidthFlag)
+ return 0x0000FFFF;
+ else
+ return cfg->Xdelta + width;
+}
+
+/**
+ ******************************************************************************
+ * @brief GFX write Modify Ydelta for align. / calc Ydelta for start
+ * @author heinrichs weikamp gmbh
+ * @version V0.0.1
+ * @date 22-April-2014
+ ******************************************************************************
+ *
+ * @param *hgfx: check gfx_engine.h.
+ * @param *cfg: Ydelta, Font
+ * @param *pText: character
+ * @retval Ydelta: 0 if text has to start left ( and probably does not fit)
+ */
+
+static uint32_t GFX_write__Modify_Xdelta__Centered(GFX_CfgWriteString* cfg, GFX_DrawCfgWindow* hgfx, const char *pTextInput)
+{
+ char cText[101];
+ uint32_t result;
+ uint32_t Xsum;
+ uint32_t j;
+ uint32_t pText;
+ uint16_t decodeUTF8;
+ uint8_t tinyState = 0; /* used to identify the usage of tiny font */
+ tFont* ptargetFont;
+
+ pText = (uint32_t)&cText[0];
+ Xsum = 0;
+ j = 0;
+ ptargetFont = (tFont *)cfg->font;
+ while (*(char*)pText != 0)// und fehlend: Abfrage window / image size
+ {
+ if(*(char*)pText == '\016') /* request font change */
+ {
+ tinyState++;
+ }
+ if(*(char*)pText == '\017') /* request font reset */
+ {
+ tinyState = 0;
+ }
+
+ if((ptargetFont == &FontT105) && ((*(char*)pText == '.') || (*(char*)pText == ':')))
+ {
+ tinyState++;
+ }
+
+ if(tinyState > 1)
+ {
+ ptargetFont = (tFont *)cfg->TinyFont;
+ }
+ else
+ {
+ ptargetFont = (tFont *)cfg->font;
+ }
+
+ decodeUTF8 = *(char*)pText; /* place ASCII char */
+ if((*(char*)pText == '\005') || (*(char*)pText == '\006'))
+ {
+ Xsum += 45;
+ }
+ else
+ {
+ if((*(char*)pText) & 0x80) /* Identify a UNICODE character other than standard ASCII using the highest bit */
+ {
+ decodeUTF8 = ((*(char*)pText) & 0x1F) << 6; /* use 5bits of first byte for upper part of unicode */
+ pText++;
+ decodeUTF8 |= (*(char*)pText) & 0x3F; /* add lower 6bits as second part of the unicode */
+ }
+ else
+ {
+ decodeUTF8 = *(char*)pText; /* place ASCII char */
+ }
+ Xsum += GFX_Character_Width(decodeUTF8, ptargetFont);
+ }
+
+ pText++;
+ j++;
+ if((ptargetFont == &FontT144) && (*(char*)pText != 0))
+ Xsum += 3;
+ else
+ if((ptargetFont == &FontT105) && (*(char*)pText != 0))
+ Xsum += 2;
+ }
+ pText -= j;
+
+ if(cfg->doubleSize)
+ Xsum *= 2;
+
+ result = hgfx->WindowX1 - hgfx->WindowX0;
+ if(Xsum < result)
+ {
+ result -= Xsum;
+ result /= 2;
+ }
+ else
+ result = 0;
+ return result;
+}
+
+
+static uint32_t GFX_write__Modify_Xdelta__RightAlign(GFX_CfgWriteString* cfg, GFX_DrawCfgWindow* hgfx, const char *pTextInput)
+{
+ uint32_t result;
+ uint32_t Xsum;
+ uint32_t j;
+ tFont *font;
+ char cText[101];
+ uint32_t pText;
+ uint16_t decodeUTF8;
+ uint8_t tinyState = 0; /* used to identify the usage of tiny font */
+
+ cText[0] = 0;
+
+// -----------------------------
+ pText = (uint32_t)&cText[0];
+// -----------------------------
+
+ font = (tFont *)cfg->font;
+ Xsum = 0;
+ j = 0;
+
+ while (*(char*)pText != 0)// und fehlend: Abfrage window / image size
+ {
+ if(*(char*)pText == '\016') /* request font change */
+ {
+ tinyState++;
+ }
+ if(*(char*)pText == '\017') /* request font reset */
+ {
+ tinyState = 0;
+ }
+
+ if((font == &FontT144) && (*(char*)pText == '.'))
+ {
+ tinyState++;
+ }
+ if((font == &FontT105) && ((*(char*)pText == '.') || (*(char*)pText == ':')))
+ {
+ tinyState++;
+ }
+
+ if(tinyState > 1)
+ {
+ font = (tFont *)cfg->TinyFont;
+ }
+ else
+ {
+ font = (tFont *)cfg->font;
+ }
+
+ if(*(char*)pText == ' ')
+ {
+ Xsum += font->spacesize;
+ }
+ else
+ if((*(char*)pText == '\005') || (*(char*)pText == '\006'))
+ {
+ Xsum += 45;
+ }
+ else
+ {
+ if((*(char*)pText) & 0x80) /* Identify a UNICODE character other than standard ASCII using the highest bit */
+ {
+ decodeUTF8 = ((*(char*)pText) & 0x1F) << 6; /* use 5bits of first byte for upper part of unicode */
+ pText++;
+ decodeUTF8 |= (*(char*)pText) & 0x3F; /* add lower 6bits as second part of the unicode */
+ }
+ else
+ {
+ decodeUTF8 = *(char*)pText;
+ }
+ Xsum += GFX_Character_Width(decodeUTF8, font); /* lookup character and add width */
+ }
+ pText++;
+ j++;
+ if((font == &FontT144) && (*(char*)pText != 0))
+ Xsum += 3;
+ else
+ if((font == &FontT105) && (*(char*)pText != 0))
+ Xsum += 2;
+ }
+ pText -= j;
+
+ if(cfg->doubleSize)
+ Xsum *= 2;
+
+ result = hgfx->WindowX1 - hgfx->WindowX0 - 1;
+ if(Xsum < result)
+ result -= Xsum;
+ else
+ result = 0;
+
+ return result;
+}
+
+void GFX_LTDC_Init(void)
+{
+ GFX_LTDC_Init_display1();
+}
+
+void GFX_LTDC_Init_display1(void)
+{
+ /* Timing configuration */
+#define ActiveH_d1 800
+#define ActiveW_d1 480
+
+#define Hsync_d1 2
+#define HFP_d1 8
+#define HBP_d1 8
+
+#define Vsync_d1 2
+#define VFP_d1 4 // make sure this value * VSYNC is also set in display.c for OLED_VFP_SET
+#define VBP_d1 4 // make sure this value * VSYNC is also set in display.c for OLED_VBP_SET
+
+ /* Horizontal synchronization width = Hsync - 1 */
+ LtdcHandle.Init.HorizontalSync = Hsync_d1 - 1;
+ /* Vertical synchronization height = Vsync - 1 */
+ LtdcHandle.Init.VerticalSync = Vsync_d1 -1;
+ /* Accumulated horizontal back porch = Hsync + HBP - 1 */
+ LtdcHandle.Init.AccumulatedHBP = Hsync_d1 + HBP_d1 - 1;
+ /* Accumulated vertical back porch = Vsync + VBP - 1 */
+ LtdcHandle.Init.AccumulatedVBP = Vsync_d1 + VBP_d1 - 1;
+ /* Accumulated active width = Hsync + HBP + Active Width - 1 */
+ LtdcHandle.Init.AccumulatedActiveW = Hsync_d1 + HBP_d1 + ActiveW_d1 - 1;
+ /* Accumulated active height = Vsync + VBP + Active Heigh - 1 */
+ LtdcHandle.Init.AccumulatedActiveH = Vsync_d1 + VBP_d1 + ActiveH_d1 - 1;
+ /* Total width = Hsync + HBP + Active Width + HFP - 1 */
+ LtdcHandle.Init.TotalWidth = Hsync_d1 + HBP_d1 + ActiveW_d1 + HFP_d1 - 1;
+ /* Total height = Vsync + VBP + Active Heigh + VFP - 1 */
+ LtdcHandle.Init.TotalHeigh = Vsync_d1 + VBP_d1 + ActiveH_d1 + VFP_d1 - 1;
+
+ /* Configure R,G,B component values for LCD background color */
+ LtdcHandle.Init.Backcolor.Red= 0;
+ LtdcHandle.Init.Backcolor.Blue= 0;
+ LtdcHandle.Init.Backcolor.Green= 0;
+
+ /* LCD clock configuration */
+ /* PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */
+ /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 192 Mhz */
+ /* PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 192/4 = 48 Mhz */
+ /* LTDC clock frequency = PLLLCDCLK / LTDC_PLLSAI_DIVR_8 = 48/4 = 6Mhz */
+
+/* done in base.c SystemClockConfig
+
+ PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
+ PeriphClkInitStruct.PLLSAI.PLLSAIN = 192;
+ PeriphClkInitStruct.PLLSAI.PLLSAIR = 4;
+ PeriphClkInitStruct.PLLSAIDivR = RCC_PLLSAIDIVR_8;
+ HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
+*/
+ /* Polarity */
+ LtdcHandle.Init.HSPolarity = LTDC_HSPOLARITY_AL;
+ LtdcHandle.Init.VSPolarity = LTDC_VSPOLARITY_AL;
+ LtdcHandle.Init.DEPolarity = LTDC_DEPOLARITY_AL;
+ LtdcHandle.Init.PCPolarity = LTDC_PCPOLARITY_IIPC;//LTDC_PCPOLARITY_IPC;
+
+ LtdcHandle.Instance = LTDC;
+
+ /* Configure the LTDC */
+ if(HAL_LTDC_Init(&LtdcHandle) != HAL_OK) // initialize GPIO Pins, too
+ {
+ /* Initialization Error */
+ GFX_Error_Handler();
+ }
+}
+
+void GFX_LTDC_LayerDefaultInit(uint16_t LayerIndex, uint32_t FB_Address)
+{
+ LTDC_LayerCfgTypeDef Layercfg;
+
+ /* Layer Init */
+ Layercfg.WindowX0 = 0;
+ Layercfg.WindowX1 = 480;
+ Layercfg.WindowY0 = 0;
+ Layercfg.WindowY1 = 800;
+ Layercfg.PixelFormat = LTDC_PIXEL_FORMAT_AL88;//LTDC_PIXEL_FORMAT_ARGB8888;
+ Layercfg.FBStartAdress = FB_Address;
+ Layercfg.Alpha = 255;
+ Layercfg.Alpha0 = 0;
+ Layercfg.Backcolor.Blue = 0;
+ Layercfg.Backcolor.Green = 0;
+ Layercfg.Backcolor.Red = 0;
+ Layercfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA;
+ Layercfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA;
+ Layercfg.ImageWidth = 480;
+ Layercfg.ImageHeight = 800;
+
+ HAL_LTDC_ConfigCLUT(&LtdcHandle, ColorLUT, CLUT_END, LayerIndex);
+ HAL_LTDC_ConfigLayer(&LtdcHandle, &Layercfg, LayerIndex);
+ HAL_LTDC_EnableCLUT(&LtdcHandle, LayerIndex);
+}
+
+static uint32_t GFX_doubleBufferOne(void)
+{
+ return SDRAM_DOUBLE_BUFFER_ONE;
+}
+
+
+static uint32_t GFX_doubleBufferTwo(void)
+{
+ return SDRAM_DOUBLE_BUFFER_TWO;
+}
+
+uint32_t getFrame(uint8_t callerId)
+{
+ static uint8_t lastFrameProvided = 0;
+ uint8_t i;
+
+/* first iteration: look for a clear frame */
+ i = lastFrameProvided;
+ do
+ {
+ i++;
+ if(i == MAXFRAMES)
+ {
+ i = 0;
+ }
+ } while((i != lastFrameProvided) && (frame[i].status != CLEAR));
+
+ if((i < MAXFRAMES) && (frame[i].status == CLEAR))
+ {
+ frame[i].status = BLOCKED;
+ frame[i].caller = callerId;
+ lastFrameProvided = i;
+ return frame[i].StartAddress;
+ }
+
+/* second iteration: look for a frame which may be reused after clearing */
+ i = lastFrameProvided;
+ do
+ {
+ i++;
+ if(i == MAXFRAMES)
+ {
+ i = 0;
+ }
+ }while((i != lastFrameProvided) && (frame[i].status != RELEASED));
+
+
+ if((i < MAXFRAMES) && (frame[i].status == RELEASED))
+ {
+ GFX_clear_frame_immediately(frame[i].StartAddress);
+ frame[i].status = BLOCKED;
+ lastFrameProvided = i;
+ return frame[i].StartAddress;
+ }
+ return 0;
+}
+
+
+void GFX_forceReleaseFramesWithId(uint8_t callerId)
+{
+ for(int i=0; i 799)
+ XrightGimpStyle = 799;
+ if(XleftGimpStyle >= XrightGimpStyle)
+ XleftGimpStyle = 0;
+ if(YtopGimpStyle > 479)
+ YtopGimpStyle = 479;
+
+ hgfx.Image = tMscreen;
+ hgfx.WindowNumberOfTextLines = 1;
+ hgfx.WindowLineSpacing = 0;
+ hgfx.WindowTab = 0;
+
+ hgfx.WindowX0 = XleftGimpStyle;
+ hgfx.WindowX1 = XrightGimpStyle;
+ hgfx.WindowY1 = 479 - YtopGimpStyle;
+ if(hgfx.WindowY1 < Font->height)
+ hgfx.WindowY0 = 0;
+ else
+ hgfx.WindowY0 = hgfx.WindowY1 - Font->height;
+ GFX_write_string_color(Font, &hgfx, text, 0, color);
+}
+
+
+void gfx_write_topline_simple(GFX_DrawCfgScreen *tMscreen, const char *text, uint8_t color)
+{
+ GFX_DrawCfgWindow hgfx;
+ const tFont *Font = &FontT48;
+
+ hgfx.Image = tMscreen;
+ hgfx.WindowNumberOfTextLines = 1;
+ hgfx.WindowLineSpacing = 0;
+
+ hgfx.WindowTab = 0;
+ hgfx.WindowX0 = 20;
+ hgfx.WindowX1 = 779;
+
+ hgfx.WindowY1 = 479;
+ hgfx.WindowY0 = hgfx.WindowY1 - Font->height;
+ GFX_write_label(Font, &hgfx, text, color);
+}
+
+
+void gfx_write_page_number(GFX_DrawCfgScreen *tMscreen, uint8_t page, uint8_t total, uint8_t color)
+{
+ GFX_DrawCfgWindow hgfx;
+ const tFont *Font = &FontT48;
+ char text[7];
+ uint8_t i, secondDigitPage, secondDigitTotal;
+
+ if(total > 8)
+ {
+ Font = &FontT24;
+ }
+
+ hgfx.Image = tMscreen;
+ hgfx.WindowNumberOfTextLines = 1;
+ hgfx.WindowLineSpacing = 0;
+ hgfx.WindowTab = 0;
+
+ hgfx.WindowX1 = 779;
+ if(Font == &FontT24)
+ {
+ hgfx.WindowX0 = hgfx.WindowX1 - (Font->spacesize*3);
+ }
+ else
+ {
+ hgfx.WindowX0 = hgfx.WindowX1 - (Font->spacesize2Monospaced*3);
+ }
+ hgfx.WindowY1 = 479;
+ hgfx.WindowY0 = hgfx.WindowY1 - Font->height;
+ if(page > 99)
+ page = 99;
+ if(total > 99)
+ total = 99;
+
+ i = 0;
+ text[i++] = '\002';
+
+ secondDigitPage = page / 10;
+ page -= secondDigitPage * 10;
+
+ secondDigitTotal = total / 10;
+ total -= secondDigitTotal * 10;
+
+ if(secondDigitPage)
+ text[i++] = '0' + secondDigitPage;
+ text[i++] = '0' + page;
+
+ text[i++] = '/';
+
+ if(secondDigitTotal)
+ text[i++] = '0' + secondDigitTotal;
+ text[i++] = '0' + total;
+
+ text[i] = 0;
+
+ GFX_clear_window_immediately(&hgfx);
+ GFX_write_label(Font, &hgfx, text, color);
+}
+
+
+uint8_t gfx_number_to_string(uint8_t max_digits, _Bool fill, char *pText, uint32_t input)
+{
+ uint8_t digits[10];
+ uint32_t number, divider;
+ int first;
+ uint8_t out;
+
+ number = input;
+ first = 0;
+ divider = 1000000000;
+ for(int i=9;i>=0;i--)
+ {
+ digits[i] = (uint8_t)(number / divider);
+ number -= digits[i] * divider;
+ divider /= 10;
+ if((first == 0) && (digits[i] != 0))
+ first = i;
+ }
+
+ if((first + 1) > max_digits)
+ {
+ for(int i = 0; i0; k--)
+ pText[i++] = digits[k -1] + '0';
+ out = max_digits;
+ }
+ else
+ {
+ int i = 0;
+ for(int k = first; k>=0; k--)
+ pText[i++] = digits[k] + '0';
+ out = i;
+ }
+
+ return out;
+}
+
+
+ /* output is
+ * 0->
+ * |
+ * v
+ *
+ * input is
+ *
+ * ->
+ * A
+ * |
+ * 0
+ */
+void GFX_screenshot(void)
+{
+ uint32_t pSource = GFX_get_pActualFrameTop();
+ uint32_t pSourceBottom =GFX_get_pActualFrameBottom();
+ uint32_t pBottomNew = getFrame(99);
+ uint32_t pDestination = GFX_doubleBufferOne();
+ uint32_t sourceNow;
+
+
+ uint32_t bot_leftStart = FrameHandler.actualBottom.leftStart; // x0 z.B. 0
+ uint32_t bot_bottomStart = FrameHandler.actualBottom.bottomStart; // y0 z.B. 25
+ uint32_t bot_width = FrameHandler.actualBottom.width; // 800
+ uint32_t bot_height = FrameHandler.actualBottom.height; // 390
+
+ struct split
+ {
+ uint8_t blue;
+ uint8_t green;
+ uint8_t red;
+ uint8_t alpha;
+ };
+
+ union inout_u
+ {
+ uint32_t in;
+ struct split out;
+ };
+
+ union inout_u value;
+
+/* test
+ uint32_t pSourceTemp = pSource + (2*479);
+ for (int j = 0xFFFF; j > 0x00FF; j -= 0x0100)
+ {
+ *(__IO uint16_t*)pSourceTemp = j;
+ pSourceTemp += 480*2;
+ }
+*/
+ // Top Layer
+ const unsigned width = 800, height = 480;
+ const uint32_t heightX2 = height*2;
+
+ for(unsigned y = 0; y < height; y++)
+ {
+ sourceNow = pSource + 2 * ((height - 1) - y);
+ for(unsigned x = 0; x < width; x++)
+ {
+// sourceNow += 2 * height * x + 2 * (height - 1 - y);
+ value.in = ColorLUT[*(__IO uint8_t*)(sourceNow)];
+ value.out.alpha = *(__IO uint8_t*)(sourceNow + 1);
+
+ *(__IO uint8_t*)(pDestination++) = value.out.red;
+ *(__IO uint8_t*)(pDestination++) = value.out.green;
+ *(__IO uint8_t*)(pDestination++) = value.out.blue;
+ *(__IO uint8_t*)(pDestination++) = value.out.alpha;
+ sourceNow += heightX2;
+ }
+ }
+
+ // Bottom Layer
+ // build newBottom
+ pSource = pSourceBottom;
+ for(unsigned x = bot_leftStart; x < bot_leftStart+bot_width; x++)
+ {
+ for(unsigned y = bot_bottomStart; y < bot_bottomStart+bot_height; y++)
+ {
+ pDestination = pBottomNew + (2 * y);
+ pDestination += heightX2 * x;
+ *(__IO uint16_t*)(pDestination) = *(__IO uint16_t*)(pSource);
+ pSource += 2;
+ }
+ }
+
+ // output Bottom Layer
+ pSource = pBottomNew;
+ pDestination = GFX_doubleBufferTwo();
+
+ for(unsigned y = 0; y < height; y++)
+ {
+ sourceNow = pSource + 2 * ((height - 1) - y);
+ for(unsigned x = 0; x < width; x++)
+ {
+// sourceNow = pSource + 2 * height * x + 2 * (height - 1 - y);
+ value.in = ColorLUT[*(__IO uint8_t*)(sourceNow)];
+ value.out.alpha = *(__IO uint8_t*)(sourceNow + 1);
+
+ *(__IO uint8_t*)(pDestination++) = value.out.red;
+ *(__IO uint8_t*)(pDestination++) = value.out.green;
+ *(__IO uint8_t*)(pDestination++) = value.out.blue;
+ *(__IO uint8_t*)(pDestination++) = value.out.alpha;
+ sourceNow += heightX2;
+ }
+ }
+ releaseFrame(99,pBottomNew);
+/*
+ // das kommt dazu!
+ unsigned yEnd = 480 - FrameHandler.actualBottom.bottomStart;
+ unsigned yStart = yEnd - FrameHandler.actualBottom.height;
+
+ if(yStart > 0)
+ {
+ for(unsigned y = 0; y < yStart; y++)
+ for(unsigned x = 0; x < width; x++)
+ {
+ *(__IO uint8_t*)(pDestination++) = 0;
+ *(__IO uint8_t*)(pDestination++) = 0;
+ *(__IO uint8_t*)(pDestination++) = 0;
+ *(__IO uint8_t*)(pDestination++) = 0;
+ }
+ }
+ for(unsigned y = yStart; y < yEnd; y++)
+ for(unsigned x = 0; x < width; x++)
+ {
+ sourceNow = pSource + 2 * height * x + 2 * (height - 1 - y);
+ value.in = ColorLUT[*(__IO uint8_t*)(sourceNow)];
+ value.out.alpha = *(__IO uint8_t*)(sourceNow + 1);
+
+ *(__IO uint8_t*)(pDestination++) = value.out.red;
+ *(__IO uint8_t*)(pDestination++) = value.out.green;
+ *(__IO uint8_t*)(pDestination++) = value.out.blue;
+ *(__IO uint8_t*)(pDestination++) = value.out.alpha;
+ }
+ if(yEnd < 480)
+ {
+ for(unsigned y = yEnd; y < 480; y++)
+ for(unsigned x = 0; x < width; x++)
+ {
+ *(__IO uint8_t*)(pDestination++) = 0;
+ *(__IO uint8_t*)(pDestination++) = 0;
+ *(__IO uint8_t*)(pDestination++) = 0;
+ *(__IO uint8_t*)(pDestination++) = 0;
+ }
+ }
+*/
+}
+
+uint32_t GFX_Character_Width(uint8_t character, tFont *Font)
+{
+ uint32_t i;
+ for(i=0;ilength;i++)
+ {
+ if(Font->chars[i].code == character)
+ {
+ return Font->chars[i].image->width;
+ }
+ }
+
+ return 0;
+}
+
+void Gfx_colorsscheme_mod(char *text, uint8_t alternativeColor)
+{
+ char *p = text;
+ uint8_t index = 0;
+
+ while ((*p) && (index < MAX_COLOR_STRING_LENGTH))
+ {
+ if (*p == '\020')
+ {
+ if(!GFX_is_colorschemeDiveStandard())
+ {
+ *p = '\027';
+ }
+ else if(alternativeColor != 0)
+ {
+ *p += alternativeColor;
+ }
+ }
+ p++;
+ index++;
+ }
+}
+
diff -r 41136649b90d -r aeafa631147d BootLoader/Src/ostc_mini.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/BootLoader/Src/ostc_mini.c Sun Mar 30 21:32:37 2025 +0200
@@ -0,0 +1,416 @@
+///////////////////////////////////////////////////////////////////////////////
+/// -*- coding: UTF-8 -*-
+///
+/// \file Discovery/Src/ostc.c
+/// \brief Hardware specific configuration
+/// \author Heinrichs Weikamp gmbh
+/// \date 05-Dec-2014
+///
+/// \details
+///
+/// $Id$
+///////////////////////////////////////////////////////////////////////////////
+/// \par Copyright (c) 2014-2018 Heinrichs Weikamp gmbh
+///
+/// This program is free software: you can redistribute it and/or modify
+/// it under the terms of the GNU General Public License as published by
+/// the Free Software Foundation, either version 3 of the License, or
+/// (at your option) any later version.
+///
+/// This program is distributed in the hope that it will be useful,
+/// but WITHOUT ANY WARRANTY; without even the implied warranty of
+/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+/// GNU General Public License for more details.
+///
+/// You should have received a copy of the GNU General Public License
+/// along with this program. If not, see .
+//////////////////////////////////////////////////////////////////////////////
+
+/* Includes ------------------------------------------------------------------*/
+#include "ostc.h"
+#include "stm32f4xx_hal.h"
+
+
+/* Exported variables --------------------------------------------------------*/
+SPI_HandleTypeDef hspiDisplay;
+SPI_HandleTypeDef cpu2DmaSpi;
+
+
+UART_HandleTypeDef UartHandle;
+#ifdef USART_PIEZO
+UART_HandleTypeDef UartPiezoTxHandle;
+#endif
+UART_HandleTypeDef UartIR_HUD_Handle;
+
+__IO ITStatus UartReady = RESET;
+__IO ITStatus UartReadyHUD = RESET;
+
+/* Private types -------------------------------------------------------------*/
+
+/* Private variables ---------------------------------------------------------*/
+
+/* Private variables with external access via get_xxx() function -------------*/
+
+/* Exported functions --------------------------------------------------------*/
+
+/** SPI init function
+ * called from HAL
+ */
+void MX_SPI_Init(void)
+{
+ hspiDisplay.Instance = SPI5;
+ hspiDisplay.Init.Mode = SPI_MODE_MASTER;
+ hspiDisplay.Init.Direction = SPI_DIRECTION_2LINES;
+ hspiDisplay.Init.DataSize = SPI_DATASIZE_8BIT;
+ hspiDisplay.Init.CLKPolarity = SPI_POLARITY_LOW;
+ hspiDisplay.Init.CLKPhase = SPI_PHASE_1EDGE;
+ hspiDisplay.Init.NSS = SPI_NSS_SOFT;
+ hspiDisplay.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;//SPI_BAUDRATEPRESCALER_4;//SPI_BAUDRATEPRESCALER_256;
+ hspiDisplay.Init.FirstBit = SPI_FIRSTBIT_MSB;
+ hspiDisplay.Init.TIMode = SPI_TIMODE_DISABLED;
+ hspiDisplay.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
+ HAL_SPI_Init(&hspiDisplay);
+
+ cpu2DmaSpi.Instance = SPI1;
+ cpu2DmaSpi.Init.Mode = SPI_MODE_MASTER;
+ cpu2DmaSpi.Init.Direction = SPI_DIRECTION_2LINES;
+ cpu2DmaSpi.Init.DataSize = SPI_DATASIZE_8BIT;
+ cpu2DmaSpi.Init.CLKPolarity = SPI_POLARITY_LOW;
+ cpu2DmaSpi.Init.CLKPhase = SPI_PHASE_1EDGE;
+ cpu2DmaSpi.Init.NSS = SPI_NSS_SOFT;//SPI_NSS_HARD_OUTPUT;//SPI_NSS_SOFT;
+ cpu2DmaSpi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
+ cpu2DmaSpi.Init.FirstBit = SPI_FIRSTBIT_MSB;
+ cpu2DmaSpi.Init.TIMode = SPI_TIMODE_DISABLED;
+ cpu2DmaSpi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
+ cpu2DmaSpi.Init.CRCPolynomial = 7;
+
+ HAL_SPI_Init(&cpu2DmaSpi);
+}
+
+
+void MX_GPIO_Backlight_max_static_only_Init(void)
+{
+ GPIO_InitTypeDef GPIO_InitStruct;
+ TIM_BACKLIGHT_GPIO_ENABLE();
+
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;//GPIO_PULLUP; /* should be normally high */
+ GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
+
+ GPIO_InitStruct.Pin = TIM_BACKLIGHT_PIN;
+ HAL_GPIO_Init(TIM_BACKLIGHT_GPIO_PORT, &GPIO_InitStruct);
+
+ HAL_GPIO_WritePin(TIM_BACKLIGHT_GPIO_PORT,TIM_BACKLIGHT_PIN,GPIO_PIN_SET);
+}
+
+
+void MX_GPIO_One_Button_only_Init(void)
+{
+ GPIO_InitTypeDef GPIO_InitStruct;
+ BUTTON_NEXT_GPIO_ENABLE();
+
+ GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;//GPIO_PULLUP; /* should be normally high */
+ GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
+
+ GPIO_InitStruct.Pin = BUTTON_NEXT_PIN;
+ HAL_GPIO_Init(BUTTON_NEXT_GPIO_PORT, &GPIO_InitStruct);
+}
+
+
+GPIO_PinState MX_GPIO_Read_The_One_Button(void)
+{
+ return HAL_GPIO_ReadPin(BUTTON_NEXT_GPIO_PORT, BUTTON_NEXT_PIN);
+}
+
+void MX_GPIO_Init(void)
+{
+ GPIO_InitTypeDef GPIO_InitStruct;
+
+ DISPLAY_CSB_GPIO_ENABLE();
+ DISPLAY_RESETB_GPIO_ENABLE();
+ EXTFLASH_CSB_GPIO_ENABLE();
+ SMALLCPU_CSB_GPIO_ENABLE();
+ OSCILLOSCOPE_GPIO_ENABLE();
+ OSCILLOSCOPE2_GPIO_ENABLE();
+ BLE_UBLOX_DSR_GPIO_ENABLE();
+
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStruct.Pull = GPIO_PULLUP;
+ GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
+
+ GPIO_InitStruct.Pin = DISPLAY_CSB_PIN;
+ HAL_GPIO_Init(DISPLAY_CSB_GPIO_PORT, &GPIO_InitStruct);
+
+ GPIO_InitStruct.Pin = DISPLAY_RESETB_PIN;
+ HAL_GPIO_Init(DISPLAY_RESETB_GPIO_PORT, &GPIO_InitStruct);
+
+ GPIO_InitStruct.Pin = EXTFLASH_CSB_PIN;
+ HAL_GPIO_Init(EXTFLASH_CSB_GPIO_PORT, &GPIO_InitStruct);
+
+ GPIO_InitStruct.Pin = OSCILLOSCOPE_PIN;
+ HAL_GPIO_Init(OSCILLOSCOPE_GPIO_PORT, &GPIO_InitStruct);
+
+ GPIO_InitStruct.Pin = OSCILLOSCOPE2_PIN;
+ HAL_GPIO_Init(OSCILLOSCOPE2_GPIO_PORT, &GPIO_InitStruct);
+
+#ifdef DISPLAY_BACKLIGHT_PIN
+ DISPLAY_BACKLIGHT_GPIO_ENABLE();
+ GPIO_InitStruct.Pin = DISPLAY_BACKLIGHT_PIN;
+ HAL_GPIO_Init(DISPLAY_BACKLIGHT_GPIO_PORT, &GPIO_InitStruct);
+ HAL_GPIO_WritePin(DISPLAY_BACKLIGHT_GPIO_PORT,DISPLAY_BACKLIGHT_PIN,GPIO_PIN_SET);
+#endif
+
+#ifdef SMALLCPU_CSB_PIN
+ SMALLCPU_CSB_GPIO_ENABLE();
+ GPIO_InitStruct.Pin = SMALLCPU_CSB_PIN;
+ HAL_GPIO_Init(SMALLCPU_CSB_GPIO_PORT, &GPIO_InitStruct);
+ HAL_GPIO_WritePin(SMALLCPU_CSB_GPIO_PORT,SMALLCPU_CSB_PIN,GPIO_PIN_SET);
+#endif
+
+#ifdef SMALLCPU_BOOT0_PIN
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ SMALLCPU_BOOT0_GPIO_ENABLE();
+ GPIO_InitStruct.Pin = SMALLCPU_BOOT0_PIN;
+ HAL_GPIO_Init(SMALLCPU_BOOT0_GPIO_PORT, &GPIO_InitStruct);
+ HAL_GPIO_WritePin(SMALLCPU_BOOT0_GPIO_PORT,SMALLCPU_BOOT0_PIN,GPIO_PIN_RESET);
+ GPIO_InitStruct.Pull = GPIO_PULLUP;
+#endif
+
+#ifdef IR_HUD_ENABLE_PIN
+ IR_HUD_ENABLE_GPIO_ENABLE();
+ GPIO_InitStruct.Pin = IR_HUD_ENABLE_PIN;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(IR_HUD_ENABLE_GPIO_PORT, &GPIO_InitStruct);
+ HAL_GPIO_WritePin(IR_HUD_ENABLE_GPIO_PORT,IR_HUD_ENABLE_PIN,GPIO_PIN_SET);
+ GPIO_InitStruct.Pull = GPIO_PULLUP;
+#endif
+
+#ifdef BLE_NENABLE_PIN
+ BLE_NENABLE_GPIO_ENABLE();
+ MX_Bluetooth_PowerOff();
+#endif
+
+#ifdef TESTPIN
+ GPIO_InitStruct.Pull = GPIO_PULLUP;
+ TEST_GPIO_ENABLE();
+ GPIO_InitStruct.Pin = TEST_PIN;
+ HAL_GPIO_Init(TEST_GPIO_PORT, &GPIO_InitStruct);
+ HAL_GPIO_WritePin(TEST_GPIO_PORT,TEST_PIN,GPIO_PIN_SET);
+ GPIO_InitStruct.Pull = GPIO_PULLUP;
+#endif
+}
+
+
+void MX_TestPin_High(void)
+{
+#ifdef TESTPIN
+ HAL_GPIO_WritePin(TEST_GPIO_PORT,TEST_PIN,GPIO_PIN_SET);
+#endif
+}
+
+
+void MX_TestPin_Low(void)
+{
+#ifdef TESTPIN
+ HAL_GPIO_WritePin(TEST_GPIO_PORT,TEST_PIN,GPIO_PIN_RESET);
+#endif
+}
+
+void MX_Bluetooth_PowerOn(void)
+{
+ GPIO_InitTypeDef GPIO_InitStruct;
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
+ GPIO_InitStruct.Pin = BLE_NENABLE_PIN;
+ HAL_GPIO_Init(BLE_NENABLE_GPIO_PORT, &GPIO_InitStruct);
+ HAL_GPIO_WritePin(BLE_NENABLE_GPIO_PORT,BLE_NENABLE_PIN,GPIO_PIN_RESET);
+
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStruct.Pull = GPIO_PULLDOWN;
+ GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
+ GPIO_InitStruct.Pin = BLE_UBLOX_DSR_PIN;
+ HAL_GPIO_Init(BLE_UBLOX_DSR_GPIO_PORT, &GPIO_InitStruct);
+ HAL_GPIO_WritePin(BLE_UBLOX_DSR_GPIO_PORT,BLE_UBLOX_DSR_PIN,GPIO_PIN_RESET);
+}
+
+
+void MX_Bluetooth_PowerOff(void)
+{
+ GPIO_InitTypeDef GPIO_InitStruct;
+ GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
+ GPIO_InitStruct.Pin = BLE_NENABLE_PIN;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ HAL_GPIO_Init(BLE_NENABLE_GPIO_PORT, &GPIO_InitStruct);
+ HAL_GPIO_WritePin(BLE_UBLOX_DSR_GPIO_PORT,BLE_UBLOX_DSR_PIN,GPIO_PIN_RESET);
+}
+
+
+void MX_SmallCPU_Reset_To_Boot(void)
+{
+#ifdef SMALLCPU_NRESET_PIN
+ GPIO_InitTypeDef GPIO_InitStruct;
+
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
+
+ SMALLCPU_NRESET_GPIO_ENABLE();
+ GPIO_InitStruct.Pin = SMALLCPU_NRESET_PIN;
+ HAL_GPIO_Init(SMALLCPU_NRESET_GPIO_PORT, &GPIO_InitStruct);
+ HAL_GPIO_WritePin(SMALLCPU_NRESET_GPIO_PORT,SMALLCPU_NRESET_PIN,GPIO_PIN_RESET);
+ HAL_GPIO_WritePin(SMALLCPU_BOOT0_GPIO_PORT,SMALLCPU_BOOT0_PIN,GPIO_PIN_SET);
+ HAL_Delay(2);
+ GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
+ HAL_GPIO_Init(SMALLCPU_NRESET_GPIO_PORT, &GPIO_InitStruct);
+ HAL_Delay(100);
+ HAL_GPIO_WritePin(SMALLCPU_BOOT0_GPIO_PORT,SMALLCPU_BOOT0_PIN,GPIO_PIN_RESET);
+#endif
+}
+
+
+void MX_SmallCPU_NO_Reset_Helper(void)
+{
+#ifdef SMALLCPU_NRESET_PIN
+ GPIO_InitTypeDef GPIO_InitStruct;
+
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
+
+ SMALLCPU_NRESET_GPIO_ENABLE();
+ HAL_GPIO_Init(SMALLCPU_NRESET_GPIO_PORT, &GPIO_InitStruct);
+ HAL_GPIO_WritePin(SMALLCPU_NRESET_GPIO_PORT,SMALLCPU_NRESET_PIN,GPIO_PIN_SET);
+// HAL_Delay(100);
+// GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
+// HAL_GPIO_Init(SMALLCPU_NRESET_GPIO_PORT, &GPIO_InitStruct);
+#endif
+}
+
+
+void MX_SmallCPU_Reset_To_Standard(void)
+{
+#ifdef SMALLCPU_NRESET_PIN
+ GPIO_InitTypeDef GPIO_InitStruct;
+
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
+
+ SMALLCPU_NRESET_GPIO_ENABLE();
+ GPIO_InitStruct.Pin = SMALLCPU_NRESET_PIN;
+ HAL_GPIO_Init(SMALLCPU_NRESET_GPIO_PORT, &GPIO_InitStruct);
+ HAL_GPIO_WritePin(SMALLCPU_NRESET_GPIO_PORT,SMALLCPU_NRESET_PIN,GPIO_PIN_RESET);
+ HAL_GPIO_WritePin(SMALLCPU_BOOT0_GPIO_PORT,SMALLCPU_BOOT0_PIN,GPIO_PIN_RESET);
+ HAL_Delay(2);
+ GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
+ HAL_GPIO_Init(SMALLCPU_NRESET_GPIO_PORT, &GPIO_InitStruct);
+#endif
+}
+
+
+uint8_t MX_UART_ButtonAdjust(uint8_t *array)
+{
+#ifdef USART_PIEZO
+ uint8_t answer[4];
+ HAL_UART_Transmit(&UartPiezoTxHandle,array,4,1000);
+ HAL_UART_Receive(&UartPiezoTxHandle,answer,4,2000);
+ if( (answer[0] == array[0])
+ &&(answer[1] == array[1])
+ &&(answer[2] == array[2])
+ &&(answer[3] == array[3]))
+ return 1;
+#endif
+ return 0;
+}
+
+
+void MX_UART_Init(void)
+{
+ /*##-1- Configure the UART peripheral ######################################*/
+ /* Put the USART peripheral in the Asynchronous mode (UART Mode) */
+ /* UART1 configured as follow:
+ - Word Length = 8 Bits
+ - Stop Bit = One Stop bit
+ - Parity = None
+ - BaudRate = 9600 baud
+ - Hardware flow control disabled (RTS and CTS signals) */
+
+#ifdef USARTx_CTS_PIN
+ UartHandle.Init.HwFlowCtl = UART_HWCONTROL_RTS_CTS;
+#else
+ UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
+#endif
+ UartHandle.Instance = USARTx;
+ UartHandle.Init.BaudRate = 115200;
+ UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
+ UartHandle.Init.StopBits = UART_STOPBITS_1;
+ UartHandle.Init.Parity = UART_PARITY_NONE;
+ UartHandle.Init.Mode = UART_MODE_TX_RX;
+ HAL_UART_Init(&UartHandle);
+
+#ifdef USART_PIEZO
+ UartPiezoTxHandle.Instance = USART_PIEZO;
+ UartPiezoTxHandle.Init.BaudRate = 1200;
+ UartPiezoTxHandle.Init.WordLength = UART_WORDLENGTH_8B;
+ UartPiezoTxHandle.Init.StopBits = UART_STOPBITS_1;
+ UartPiezoTxHandle.Init.Parity = UART_PARITY_NONE;
+ UartPiezoTxHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
+ UartPiezoTxHandle.Init.Mode = UART_MODE_TX_RX;
+
+ HAL_UART_Init(&UartPiezoTxHandle);
+#endif
+
+#ifdef USART_IR_HUD
+ UartIR_HUD_Handle.Instance = USART_IR_HUD;
+ UartIR_HUD_Handle.Init.BaudRate = 2400;
+ UartIR_HUD_Handle.Init.WordLength = UART_WORDLENGTH_8B;
+ UartIR_HUD_Handle.Init.StopBits = UART_STOPBITS_1;
+ UartIR_HUD_Handle.Init.Parity = UART_PARITY_NONE;
+ UartIR_HUD_Handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
+ UartIR_HUD_Handle.Init.Mode = UART_MODE_TX_RX;
+
+ HAL_UART_Init(&UartIR_HUD_Handle);
+#endif
+}
+
+void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
+{
+ if(huart == &UartHandle)
+ UartReady = SET;
+}
+
+
+void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
+{
+ if(huart == &UartHandle)
+ UartReady = SET;
+ else
+ if(huart == &UartIR_HUD_Handle)
+ {
+ UartReadyHUD = SET;
+ }
+}
+
+void MX_tell_reset_logik_alles_ok(void)
+{
+#ifdef RESET_LOGIC_ALLES_OK_PIN
+ GPIO_InitTypeDef GPIO_InitStruct;
+
+ RESET_LOGIC_ALLES_OK_GPIO_ENABLE();
+
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
+ GPIO_InitStruct.Pin = RESET_LOGIC_ALLES_OK_PIN;
+ HAL_GPIO_Init(RESET_LOGIC_ALLES_OK_GPIO_PORT, &GPIO_InitStruct);
+
+ HAL_GPIO_WritePin(RESET_LOGIC_ALLES_OK_GPIO_PORT,RESET_LOGIC_ALLES_OK_PIN,GPIO_PIN_RESET);
+ HAL_Delay(1);
+ HAL_GPIO_WritePin(RESET_LOGIC_ALLES_OK_GPIO_PORT,RESET_LOGIC_ALLES_OK_PIN,GPIO_PIN_SET);
+
+ GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
+ HAL_GPIO_Init(RESET_LOGIC_ALLES_OK_GPIO_PORT, &GPIO_InitStruct);
+#endif
+}
diff -r 41136649b90d -r aeafa631147d BootLoader/Src/tComm_mini.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/BootLoader/Src/tComm_mini.c Sun Mar 30 21:32:37 2025 +0200
@@ -0,0 +1,1892 @@
+///////////////////////////////////////////////////////////////////////////////
+/// -*- coding: UTF-8 -*-
+///
+/// \file Discovery/Src/tComm.c
+/// \brief Main file for communication reduced to needs of the bootloader
+/// \author heinrichs weikamp gmbh
+/// \date 29-Mar-2025
+///
+/// \details
+///
+/// $Id$
+///////////////////////////////////////////////////////////////////////////////
+/// \par Copyright (c) 2014-2018 Heinrichs Weikamp gmbh
+///
+/// This program is free software: you can redistribute it and/or modify
+/// it under the terms of the GNU General Public License as published by
+/// the Free Software Foundation, either version 3 of the License, or
+/// (at your option) any later version.
+///
+/// This program is distributed in the hope that it will be useful,
+/// but WITHOUT ANY WARRANTY; without even the implied warranty of
+/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+/// GNU General Public License for more details.
+///
+/// You should have received a copy of the GNU General Public License
+/// along with this program. If not, see .
+//////////////////////////////////////////////////////////////////////////////
+
+/**
+ ==============================================================================
+ ##### How to use #####
+ ==============================================================================
+ ==============================================================================
+ ##### History #####
+ ==============================================================================
+ 160211 added 4 bytes Serial in update Files after checksum prior to binary
+ 160211 0x6B changed to version only
+ 160623 fixed 0x72 (in V1.0.9)
+ 160623 fixed rebuild menu (before update) for V1.0.10
+
+ ==============================================================================
+ ##### CTS / RTS #####
+ ==============================================================================
+ RTS is Output, CTS is Input
+
+ BlueMod Pin D7 UART-RTS# is Output
+ connected to STM32F429 PA11 CTS (Input)
+ also STM32 PA12 RTS is connected to BlueMod UART-CTS# F3
+
+ see BlueMod_SR_HWreference_r06.pdf, page 156
+ and MAIN_CPU STM32F4 Reference manual DM00031020.pdf, page 990
+
+
+ ==============================================================================
+ ##### Codes #####
+ ==============================================================================
+ [0x73] upload CPU2 firmware in SDRAM and update CPU2
+
+ [0x74] upload MainCPU firmware in EEPROM and start bootloader
+
+ */
+
+/* Includes ------------------------------------------------------------------*/
+
+#include "tComm.h"
+
+#include "externCPU2bootloader.h"
+#include "externLogbookFlash.h"
+#include "gfx_colors.h"
+#include "gfx_engine.h"
+#include "gfx_fonts.h"
+#include "ostc.h"
+
+#include "base_bootloader.h"
+#include "firmwareEraseProgram.h"
+#include "text_multilanguage.h"
+
+#ifdef SPECIALPROGRAMM
+# include "firmwareEraseProgram.h"
+#endif
+#include
+#include
+
+
+/* Private variables ---------------------------------------------------------*/
+GFX_DrawCfgScreen tCscreen;
+GFX_DrawCfgWindow tCwindow;
+
+uint8_t receiveStartByteUart = 0;
+uint8_t bluetoothActiveLastTime = 0;
+
+uint8_t StartListeningToUART = 0;
+char display_text[256] = { 0 };
+
+uint8_t setForcedBluetoothName = 0;
+
+uint8_t updateSettingsAndMenuOnExit = 0;
+
+/* Private types -------------------------------------------------------------*/
+#define BYTE_DOWNLOAD_MODE (0xBB)
+#define BYTE_SERVICE_MODE (0xAA)
+
+#define UART_OPERATION_TIMEOUT (500u) /* Timeout for common read / write operations (ms) */
+#define UART_TIMEOUT_SECONDS (120u) /* Timeout for keeping connection open and waiting for data */
+#define UART_TIMEOUT_LARGE_BLOCK (6000u) /* Timeout (ms) for reception of an 16K data block (typical RX time ~4,5seconds) */
+
+#define UART_CMD_BUF_SIZE (30u) /* size of buffer for command exchange */
+
+const uint8_t id_Region1_firmware = 0xFF;
+const uint8_t id_RTE = 0xFE;
+const uint8_t id_FONT = 0x10;
+const uint8_t id_FONT_OLD = 0x00;
+
+static BlueModTmpConfig_t BmTmpConfig = BM_CONFIG_OFF; /* Config BlueMod without storing the changes */
+static uint8_t EvaluateBluetoothSignalStrength = 0;
+
+/* Private function prototypes -----------------------------------------------*/
+static void tComm_Error_Handler(void);
+static uint8_t select_mode(uint8_t aRxByte);
+static uint8_t tComm_CheckAnswerOK(void);
+static uint8_t tComm_HandleBlueModConfig(void);
+static void tComm_EvaluateBluetoothStrength(void);
+uint8_t receive_update_flex(uint8_t isRTEupdateALLOWED);
+uint8_t receive_update_data_flex(uint8_t* pBuffer1, uint8_t* pBuffer2, uint8_t RTEupdateALLOWED);
+uint8_t receive_update_data_mainCPU_firmware(void);
+uint8_t receive_update_data_mainCPU_variable_firmware(void);
+uint8_t receive_update_data_mainCPU_firmware_subroutine(uint8_t region, uint8_t* pBuffer1, uint8_t* pBuffer2);
+HAL_StatusTypeDef receive_uart_large_size(UART_HandleTypeDef *huart, uint8_t *pData, uint32_t Size);
+static uint8_t openComm(uint8_t aRxByte);
+uint8_t HW_Set_Bluetooth_Name(uint16_t serial, uint8_t withEscapeSequence);
+uint8_t prompt4D4C(uint8_t mode);
+uint8_t tComm_GetBTCmdStr(BTCmd cmdId, char* pCmdStr);
+
+
+static uint8_t receive_update_data_cpu2(void);
+uint8_t receive_update_data_cpu2_sub(uint8_t* pBuffer);
+
+/* Exported functions --------------------------------------------------------*/
+
+void tComm_init(void)
+{
+ tCscreen.FBStartAdress = 0;
+ tCscreen.ImageHeight = 480;
+ tCscreen.ImageWidth = 800;
+ tCscreen.LayerIndex = 1;
+
+ tCwindow.Image = &tCscreen;
+ tCwindow.WindowNumberOfTextLines = 6;
+ tCwindow.WindowLineSpacing = 65;
+ tCwindow.WindowTab = 400;
+ tCwindow.WindowX0 = 20;
+ tCwindow.WindowX1 = 779;
+
+ tCwindow.WindowY0 = 0;
+ tCwindow.WindowY1 = 479;
+
+ StartListeningToUART = 1;
+}
+
+uint8_t tComm_control(void)
+{
+ uint8_t answer = 0;
+
+ if(BmTmpConfig != BM_CONFIG_DONE)
+ {
+ tComm_HandleBlueModConfig();
+ }
+ else
+ {
+ /*##-2- Put UART peripheral in reception process ###########################*/
+
+ if((UartReady == RESET) && StartListeningToUART)
+ {
+ StartListeningToUART = 0;
+ if(HAL_UART_Receive_IT(&UartHandle, &receiveStartByteUart, 1) != HAL_OK)
+ tComm_Error_Handler();
+ }
+ /* Reset transmission flag */
+ if(UartReady == SET)
+ {
+ UartReady = RESET;
+ if((receiveStartByteUart == BYTE_DOWNLOAD_MODE) || (receiveStartByteUart == BYTE_SERVICE_MODE))
+ answer = openComm(receiveStartByteUart);
+ StartListeningToUART = 1;
+ return answer;
+ }
+ }
+ return 0;
+}
+
+
+void tComm_refresh(void)
+{
+ char localString[255];
+
+ if(tCscreen.FBStartAdress == 0)
+ {
+ GFX_hwBackgroundOn();
+ tCscreen.FBStartAdress = getFrame(18);
+ write_content_simple(&tCscreen, 0, 800, 480-24, &FontT24,"Exit",CLUT_ButtonSurfaceScreen);
+ write_content_simple(&tCscreen, 800 - 70, 800, 480-24, &FontT24,"Signal",CLUT_ButtonSurfaceScreen);
+
+ if(receiveStartByteUart == BYTE_SERVICE_MODE)
+ GFX_write_string(&FontT48, &tCwindow, "Service mode enabled",2);
+ else
+ GFX_write_string(&FontT48, &tCwindow, "Download mode enabled",2);
+ GFX_SetFramesTopBottom(tCscreen.FBStartAdress, 0,480);
+ display_text[0] = 0;
+ display_text[255] = 0;
+ }
+ else if(display_text[255])
+ {
+ display_text[(uint8_t)display_text[255]] = 0;
+ localString[0] = TXT_MINIMAL;
+ strcpy (&localString[1],display_text);
+ releaseFrame(18,tCscreen.FBStartAdress);
+ tCscreen.FBStartAdress = getFrame(18);
+ write_content_simple(&tCscreen, 0, 800, 480-24, &FontT24,"Exit",CLUT_ButtonSurfaceScreen);
+ write_content_simple(&tCscreen, 800 - 70, 800, 480-24, &FontT24,"Signal",CLUT_ButtonSurfaceScreen);
+ GFX_write_string(&FontT48, &tCwindow, localString,2);
+ GFX_SetFrameTop(tCscreen.FBStartAdress);
+ display_text[0] = 0;
+ display_text[255] = 0;
+ }
+}
+
+
+void tComm_verlauf(uint8_t percentage_complete)
+{
+ uint32_t pDestination;
+
+ pDestination = (uint32_t)tCscreen.FBStartAdress;
+ pDestination += 150 * tCscreen.ImageHeight * 2;
+ pDestination += 100 * 2;
+
+ if(percentage_complete > 100)
+ percentage_complete = 100;
+
+ int i = 1;
+ while(i<=percentage_complete)
+ {
+ i += 1;
+ for(int y=0;y<4;y++)
+ {
+ for(int x=0;x<40;x++)
+ {
+ *(__IO uint16_t*)pDestination = 0xFF00 + 00;
+ pDestination += 2;
+ }
+ pDestination += (tCscreen.ImageHeight - 40 )* 2;
+ }
+ pDestination += tCscreen.ImageHeight * 2; // one spare line
+ }
+}
+
+
+void tComm_exit(void)
+{
+ SStateList status;
+ get_globalStateList(&status);
+
+ releaseFrame(18,tCscreen.FBStartAdress);
+ tCscreen.FBStartAdress = 0;
+ GFX_hwBackgroundOff();
+
+ if(setForcedBluetoothName)
+ {
+ setForcedBluetoothName = 0;
+ MX_Bluetooth_PowerOff();
+ HAL_Delay(1000);
+ MX_Bluetooth_PowerOn();
+ tComm_Set_Bluetooth_Name(1);
+ tComm_StartBlueModConfig();
+ }
+
+ updateSettingsAndMenuOnExit = 0;
+
+ if(status.base == BaseComm)
+ {
+ set_globalState_Base();
+ }
+ MX_Bluetooth_PowerOff(); // Power down Bluetooth on the way out
+}
+
+
+uint8_t tComm_Set_Bluetooth_Name(uint8_t force)
+{
+ uint8_t answer = 0;
+
+ if(hardwareDataGetPointer()->secondarySerial != 0xFFFF)
+ {
+ if(force || (hardwareDataGetPointer()->secondary_bluetooth_name_set == 0xFF))
+ answer = HW_Set_Bluetooth_Name(hardwareDataGetPointer()->secondarySerial, 0);
+ if(answer == HAL_OK)
+ hardware_programmSecondaryBluetoothNameSet();
+ }
+ else
+ if(hardwareDataGetPointer()->primarySerial != 0xFFFF)
+ {
+ if(force || (hardwareDataGetPointer()->production_bluetooth_name_set == 0xFF))
+ answer = HW_Set_Bluetooth_Name(hardwareDataGetPointer()->primarySerial, 0);
+
+ if(answer == HAL_OK)
+ hardware_programmPrimaryBluetoothNameSet();
+
+ }
+ else /* no serial set at all => do default configuration of the module */
+ {
+#define NINAB22103B00
+#ifdef NINAB22103B00
+ answer = 0xFF;
+#endif
+ }
+ return answer;
+}
+
+
+uint8_t HW_Set_Bluetooth_Name(uint16_t serial, uint8_t withEscapeSequence)
+{
+ uint8_t answer = HAL_OK;
+ uint8_t aRxBuffer[50];
+ char aTxBufferName[50];
+
+// char aTxFactoryDefaults[50] = "AT&F1\r";
+
+ char aTxBufferEscapeSequence[50] = "+++"; /* factory default */
+ // limit is 19 chars, with 7 chars shown in BLE advertising mode
+ //________________________123456789012345678901
+
+ tComm_GetBTCmdStr(BT_CMD_NAME, aTxBufferName);
+
+ char answerOkay[6] = "\r\nOK\r\n";
+
+ gfx_number_to_string(5,1,&aTxBufferName[15],serial);
+
+ // store active configuration in non-volatile memory
+ char aTxBufferWrite[50] = "AT&W\r";
+
+// char aTxBufferReset[50] = "AT+RESET\r";
+
+
+ HAL_Delay(1010);
+ if(withEscapeSequence)
+ {
+ aRxBuffer[0] = 0;
+ if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBufferEscapeSequence, 3, 2000)!= HAL_OK)
+ answer = HAL_ERROR;
+ HAL_UART_Receive(&UartHandle, (uint8_t*)aRxBuffer, 3, 2000);
+ HAL_Delay(1010);
+
+ for(int i=0;i<3;i++)
+ if(aRxBuffer[i] != '+')
+ answer = HAL_ERROR;
+ }
+
+ aRxBuffer[0] = 0;
+ if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBufferName, 21, 2000)!= HAL_OK)
+ answer = HAL_ERROR;
+ HAL_UART_Receive(&UartHandle, (uint8_t*)aRxBuffer, 21+6, 2000);
+
+ for(int i=0;i<21;i++)
+ if(aRxBuffer[i] != aTxBufferName[i])
+ answer = HAL_ERROR;
+
+ for(int i=0;i<6;i++)
+ if(aRxBuffer[21+i] != answerOkay[i])
+ answer = HAL_ERROR;
+
+ HAL_Delay(200);
+
+ if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBufferWrite, 5, 2000)!= HAL_OK)
+ answer = HAL_ERROR;
+ HAL_UART_Receive(&UartHandle, (uint8_t*)aRxBuffer, 5+6, 2000);
+
+ for(int i=0;i<5;i++)
+ if(aRxBuffer[i] != aTxBufferWrite[i])
+ answer = HAL_ERROR;
+
+ for(int i=0;i<6;i++)
+ if(aRxBuffer[5+i] != answerOkay[i])
+ answer = HAL_ERROR;
+
+ answer = HAL_OK;
+ return answer;
+}
+
+uint8_t openComm(uint8_t aRxByte)
+{
+ SStateList status;
+ uint8_t localRx;
+ uint8_t timeoutCounter = 0;
+ uint8_t answer = 0;
+ uint8_t service_mode_last_three_bytes[3];
+ uint8_t service_mode_response[5] =
+ {
+ 0x4B,
+ 0xAB,
+ 0xCD,
+ 0xEF,
+ 0x4C
+ };
+ uint8_t download_mode_response[2] =
+ {
+ 0xBB,
+ 0x4D
+ };
+
+ if((aRxByte != BYTE_DOWNLOAD_MODE) && (aRxByte != BYTE_SERVICE_MODE))
+ return 0;
+
+ set_globalState(StUART_STANDARD);
+
+ /* service mode is four bytes
+ 0xAA 0xAB 0xCD 0xEF
+ answer is
+ */
+ localRx = aRxByte;
+
+ if(aRxByte == BYTE_SERVICE_MODE)
+ {
+ if((HAL_UART_Receive(&UartHandle, (uint8_t*)service_mode_last_three_bytes, 3, 2000)!= HAL_OK))
+ answer = 0x00;
+ else
+ {
+ if((service_mode_last_three_bytes[0] != 0xAB) || (service_mode_last_three_bytes[1] != 0xCD) || (service_mode_last_three_bytes[2] != 0xEF))
+ answer = 0x00;
+ else
+ {
+ if(HAL_UART_Transmit(&UartHandle, (uint8_t*)service_mode_response, 5, 2000)!= HAL_OK)
+ answer = 0x00;
+ else
+ answer = prompt4D4C(receiveStartByteUart);
+ }
+ }
+ }
+ else //if(aRxByte == BYTE_SERVICE_MODE)
+ {
+ if(HAL_UART_Transmit(&UartHandle, (uint8_t*)download_mode_response, 2, 2000)!= HAL_OK)
+ answer = 0x00;
+ else
+ answer = prompt4D4C(receiveStartByteUart);
+ }
+
+ while((answer == prompt4D4C(receiveStartByteUart)) && (timeoutCounter < UART_TIMEOUT_SECONDS)) /* try receive once a second */
+ {
+ if(HAL_UART_Receive(&UartHandle, (uint8_t*)&localRx, 1, UART_OPERATION_TIMEOUT)!= HAL_OK)
+ {
+ timeoutCounter++;
+ get_globalStateList(&status);
+ if (status.base != BaseComm)
+ {
+ timeoutCounter = UART_TIMEOUT_SECONDS; /* Abort action triggered outside main loop => exit */
+ }
+ if(EvaluateBluetoothSignalStrength)
+ {
+ tComm_EvaluateBluetoothStrength();
+ }
+ }
+ else
+ {
+ answer = select_mode(localRx);
+ timeoutCounter = 0;
+ }
+ }
+ set_returnFromComm();
+ return 1;
+}
+
+
+uint8_t prompt4D4C(uint8_t mode)
+{
+ if(mode == BYTE_SERVICE_MODE)
+ return 0x4C;
+ else
+ return 0x4D;
+}
+
+
+uint8_t select_mode(uint8_t type)
+{
+ uint8_t dummyForBootloader[256] = {0};
+ uint8_t count;
+ uint8_t aTxBuffer[128];
+ uint8_t aRxBuffer[68];
+ uint8_t answer;
+ aTxBuffer[0] = type;
+ aTxBuffer[1] = prompt4D4C(receiveStartByteUart);
+ uint8_t tempHigh, tempLow;
+ count = 0;
+
+ // service mode only commands
+ if(receiveStartByteUart == BYTE_SERVICE_MODE)
+ {
+ // first part
+ switch(type)
+ {
+ // start communication (again)
+ case 0xAA:
+ if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBuffer, 2, 1000)!= HAL_OK)
+ return 0;
+ else
+ return prompt4D4C(receiveStartByteUart);
+ default:
+ break;
+ }
+
+
+ // Exit communication on Text like RING, CONNECT, ... or 0xFF command
+ if((type < 0x60) || (type == 0xFF))
+ return 0;
+
+ // return of command for (almost) all commands
+ switch(type)
+ {
+ // not supported yet case 0x20: // send hi:lo:temp1 bytes starting from ext_flash_address:3
+ // not supported yet case 0x22: // Resets all logbook pointers and the logbook (!)
+ // not supported yet case 0x23: // Resets battery gauge registers
+ // not supported yet case 0x30: // write bytes starting from ext_flash_address:3 (Stop when timeout)
+ // not supported yet case 0x40: // erases 4kB block from ext_flash_address:3 (Warning: No confirmation or built-in security here...)
+ // not supported yet case 0x42: // erases range in 4kB steps (Get 3 bytes address and 1byte amount of 4kB blocks)
+ // not supported yet case 0x50: // sends firmware from external flash from 0x3E0000 to 0x3FD000 (118784bytes) via comm
+ case 0xFE: // hw unit_tests
+ case 0x71: // hw read manufacturing data
+ case 0x73: // hw update FLEX
+ case 0x79: // hw read device data
+ case 0x74: // hw update Firmware
+ case 0x75: // hw update RTE
+ case 0x76: // hw update Fonts
+ case 0x80: // hw write manufacturing data
+ case 0x81: // hw write second serial
+ case 0x82: // hw set bluetooth name
+ case 0xC1: // Start low-level bootloader
+ if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBuffer, 1, UART_OPERATION_TIMEOUT)!= HAL_OK)
+ return 0;
+ break;
+ default:
+ break;
+ }
+
+ // now send content or update firmware
+ switch(type)
+ {
+ case 0xFE:
+ // work to do :-) 12. Oct. 2015
+ // 256 bytes output
+ memset(aTxBuffer,0,128);
+ if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBuffer, 128,5000)!= HAL_OK)
+ return 0;
+ if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBuffer, 128,5000)!= HAL_OK)
+ return 0;
+ aTxBuffer[count++] = prompt4D4C(receiveStartByteUart);
+ break;
+
+ case 0x71:
+ memcpy(aTxBuffer,hardwareDataGetPointer(),64);
+ count += 64;
+ aTxBuffer[count++] = prompt4D4C(receiveStartByteUart);
+ break;
+
+ case 0x73:
+ answer = receive_update_flex(0);
+ if(answer == 0)
+ return 0;
+ else if(answer == 2) // 2 = RTE without bootToBootloader
+ {
+ aTxBuffer[0] = 0xFF;
+ HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBuffer, 1,10000);
+ return 0;
+ }
+ else
+ {
+ aTxBuffer[count++] = prompt4D4C(receiveStartByteUart);
+ if(answer == 1) /* 0xFF is checksum error, 2 = RTE without bootToBootloader */
+ {
+ extern uint8_t bootToBootloader;
+ bootToBootloader = 1;
+ }
+ }
+ break;
+
+ case 0x79:
+ if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBuffer, 1,10000)!= HAL_OK)
+ return 0;
+ ext_flash_read_fixed_16_devicedata_blocks_formated_128byte_total(aTxBuffer);
+ if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBuffer, 128,5000)!= HAL_OK)
+ return 0;
+ aTxBuffer[0] = prompt4D4C(receiveStartByteUart);
+ if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBuffer, 1,10000)!= HAL_OK)
+ return 0;
+ else
+ return prompt4D4C(receiveStartByteUart);
+
+ case 0x82:
+ setForcedBluetoothName = 1;
+ return 0;
+
+ case 0x74:
+ answer = receive_update_data_mainCPU_firmware();
+ if(answer != 0)
+ {
+ aTxBuffer[count++] = prompt4D4C(receiveStartByteUart);
+ if(answer == 1) // 0xFF is checksum error
+ {
+ extern uint8_t bootToBootloader;
+ bootToBootloader = 1;
+ }
+ }
+ else
+ return 0;
+ break;
+
+ case 0x75:
+ receive_update_data_cpu2();
+ aTxBuffer[count++] = prompt4D4C(receiveStartByteUart);
+ break;
+
+ case 0x76:
+ answer = receive_update_data_mainCPU_variable_firmware();
+ if(answer != 0)
+ {
+ aTxBuffer[count++] = prompt4D4C(receiveStartByteUart);
+ if(answer == 1) // 0xFF is checksum error
+ {
+ extern uint8_t bootToBootloader;
+ bootToBootloader = 1;
+ }
+ }
+ else
+ return 0;
+ break;
+
+ case 0x80:
+ if(HAL_UART_Receive(&UartHandle, (uint8_t*)aRxBuffer, 52, 5000)!= HAL_OK)
+ return 0;
+ if(hardware_programmProductionData(aRxBuffer) == HAL_OK)
+ {
+ aTxBuffer[count++] = prompt4D4C(receiveStartByteUart);
+ }
+ else
+ return 0;
+ break;
+
+ case 0x81:
+ if(HAL_UART_Receive(&UartHandle, (uint8_t*)aRxBuffer, 12, 1000)!= HAL_OK)
+ return 0;
+ if(hardware_programmSecondarySerial(aRxBuffer) == HAL_OK)
+ {
+ aTxBuffer[count++] = prompt4D4C(receiveStartByteUart);
+ }
+ else
+ return 0;
+ break;
+
+ }
+
+ // was service command? Yes, finish and exit
+ if(count)
+ {
+ if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBuffer, count,10000)!= HAL_OK)
+ return 0;
+ else
+ return prompt4D4C(receiveStartByteUart);
+ }
+ }
+
+
+ // download mode commands
+ switch(type)
+ {
+ // return of command for almost all commands
+ case 0x60: // get model + features
+ case 0x61: // get all headers full (256 bytes)
+ case 0x62: // set clock
+ case 0x63: // set custom text
+ case 0x66: // get dive profile
+ case 0x69: // get serial, old version numbering, custom text
+ case 0x6A: // get model
+ case 0x6B: // get specific firmware version
+ case 0x6C: /* Display Bluetooth signal strength */
+ case 0x6D: // get all compact headers (16 byte)
+ case 0x6E: // display text
+ case 0x70: // read min, default, max setting
+ case 0x72: // read setting
+ case 0x77: // write setting
+ case 0x78: // reset all settings
+ if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBuffer, 1, 1000)!= HAL_OK)
+ return 0;
+ break;
+
+ // start communication (again)
+ case 0xBB:
+ if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBuffer, 2, 1000)!= HAL_OK)
+ return 0;
+ else
+ return prompt4D4C(receiveStartByteUart);
+
+ // stop communication
+ case 0xFF:
+ HAL_UART_Transmit(&UartHandle, (uint8_t*)&aTxBuffer, 1, 1000);
+ return 0;
+
+ default:
+ aTxBuffer[count++] = prompt4D4C(receiveStartByteUart);
+ break;
+ }
+
+ switch(type)
+ {
+ case 0x62:
+ if(HAL_UART_Receive(&UartHandle, (uint8_t*)aRxBuffer, 6, 2000)!= HAL_OK)
+ return 0;
+ break;
+ case 0x63:
+ if(HAL_UART_Receive(&UartHandle, (uint8_t*)aRxBuffer, 60, 5000)!= HAL_OK)
+ return 0;
+ break;
+ case 0x66:
+ if(HAL_UART_Receive(&UartHandle, (uint8_t*)aRxBuffer, 1, 1000)!= HAL_OK)
+ return 0;
+ break;
+ case 0x6B:
+ if(HAL_UART_Receive(&UartHandle, (uint8_t*)aRxBuffer, 1, 1000)!= HAL_OK)
+ return 0;
+ break;
+ case 0x6E:
+ if(HAL_UART_Receive(&UartHandle, (uint8_t*)aRxBuffer, 16, 5000)!= HAL_OK)
+ return 0;
+ break;
+ case 0x77:
+ if(HAL_UART_Receive(&UartHandle, (uint8_t*)aRxBuffer, 5, 5000)!= HAL_OK)
+ return 0;
+ break;
+ case 0x72:
+ if(HAL_UART_Receive(&UartHandle, (uint8_t*)aRxBuffer, 1, 5000)!= HAL_OK)
+ return 0;
+ break;
+ case 0x70:
+ if(HAL_UART_Receive(&UartHandle, (uint8_t*)aRxBuffer, 1, 5000)!= HAL_OK)
+ return 0;
+ break;
+ }
+
+ switch(type)
+ {
+ /* common to standard and bootloader */
+
+ // get model + features
+ case 0x60:
+ aTxBuffer[count++] = 0x00; // hardware descriptor HIGH byte
+ aTxBuffer[count++] = 0x3B; // hardware descriptor LOW byte // 0x3B is OSTC4 // 0x1A is OTSC3
+ aTxBuffer[count++] = 0x00; // feature descriptor HIGH byte
+ aTxBuffer[count++] = 0x00; // feature descriptor LOW byte
+ aTxBuffer[count++] = 0x43; // model id
+ aTxBuffer[count++] = prompt4D4C(receiveStartByteUart);
+ break;
+
+ // get model
+ case 0x6A:
+ aTxBuffer[count++] = 0x3B; // 0x3B is OSTC4 // 0x1A is OTSC3
+ aTxBuffer[count++] = prompt4D4C(receiveStartByteUart);
+ break;
+
+ // get all firmware version and status (OSTC4 only)
+ case 0x6B:
+ switch(*aRxBuffer)
+ {
+ case 0xFF:
+ // firmware
+ aTxBuffer[count++] = firmwareDataGetPointer()->versionFirst;
+ aTxBuffer[count++] = firmwareDataGetPointer()->versionSecond;
+ aTxBuffer[count++] = firmwareDataGetPointer()->versionThird;
+ aTxBuffer[count++] = firmwareDataGetPointer()->versionBeta;
+ break;
+ case 0xFE:
+ // RTE
+ getActualRTEandFONTversion(&tempHigh, &tempLow, 0, 0); // RTE
+ aTxBuffer[count++] = tempHigh;
+ aTxBuffer[count++] = tempLow;
+ aTxBuffer[count++] = 0;
+ aTxBuffer[count++] = 0;
+ break;
+ case 0x10:
+ getActualRTEandFONTversion( 0, 0, &tempHigh, &tempLow); // font
+ aTxBuffer[count++] = tempHigh;
+ aTxBuffer[count++] = tempLow;
+ aTxBuffer[count++] = 0;
+ aTxBuffer[count++] = 0;
+ break;
+ default:
+ // not supported
+ aTxBuffer[count++] = 0xFF;
+ aTxBuffer[count++] = 0xFF;
+ aTxBuffer[count++] = 0xFF;
+ aTxBuffer[count++] = 0xFF;
+ break;
+/* Jef Driesen Test
+ default:
+ // not supported
+ aTxBuffer[count++] = 0x1;
+ aTxBuffer[count++] = 0x1;
+ aTxBuffer[count++] = 0x1;
+ aTxBuffer[count++] = 0x1;
+ break;
+*/
+ }
+/*
+ // serial
+ aTxBuffer[count++] = pSettings->serialLow;
+ aTxBuffer[count++] = pSettings->serialHigh;
+ // batch code (date)
+ hardwareBatchCode(&tempHigh, &tempLow);
+ aTxBuffer[count++] = tempLow;
+ aTxBuffer[count++] = tempHigh;
+ // status and status detail (future feature)
+ aTxBuffer[count++] = 0;
+ aTxBuffer[count++] = 0;
+ aTxBuffer[count++] = 0;
+ aTxBuffer[count++] = 0;
+*/
+ // prompt
+ aTxBuffer[count++] = prompt4D4C(receiveStartByteUart);
+ break;
+
+ /* Trigger Bluetooth signal strength evaluation */
+ case 0x6C: tComm_EvaluateBluetoothStrength();
+ aTxBuffer[count++] = prompt4D4C(receiveStartByteUart);
+ break;
+ // display text
+ case 0x6E:
+ for(int i=0;i<16;i++)
+ display_text[i] = aRxBuffer[i];
+ display_text[15] = 0;
+ display_text[255] = 16;
+ aTxBuffer[count++] = prompt4D4C(receiveStartByteUart);
+ break;
+
+ // version / identify
+ case 0x69:
+ aTxBuffer[count++] = 0;//pSettings->serialLow;
+ aTxBuffer[count++] = 0;//pSettings->serialHigh;
+ aTxBuffer[count++] = 0;//firmwareVersion_16bit_low();
+ aTxBuffer[count++] = 0;//firmwareVersion_16bit_high();
+ memset(&aTxBuffer[count], 0, 60);
+ count += 60;
+ aTxBuffer[count++] = prompt4D4C(receiveStartByteUart);
+ break;
+
+ /* bootloader dummies */
+ // full headers (256 byte)
+ case 0x61:
+ for(int StepBackwards = 0;StepBackwards<256;StepBackwards++)
+ {
+ if(HAL_UART_Transmit(&UartHandle, (uint8_t*)dummyForBootloader, 256,5000)!= HAL_OK)
+ return 0;
+ }
+ aTxBuffer[count++] = prompt4D4C(receiveStartByteUart);
+ break;
+ // compact headers (16 byte)
+ case 0x6D:
+ for(int StepBackwards = 0;StepBackwards<256;StepBackwards++)
+ {
+ if(HAL_UART_Transmit(&UartHandle, (uint8_t*)dummyForBootloader, 16,5000)!= HAL_OK)
+ return 0;
+ }
+ aTxBuffer[count++] = prompt4D4C(receiveStartByteUart);
+ break;
+ // set clock & date
+ case 0x62:
+ aTxBuffer[count++] = prompt4D4C(receiveStartByteUart);
+ break;
+ // set custom text
+ case 0x63:
+ aTxBuffer[count++] = prompt4D4C(receiveStartByteUart);
+ break;
+ // get dive profile
+ case 0x66:
+ if(HAL_UART_Transmit(&UartHandle, (uint8_t*)dummyForBootloader, 256,5000)!= HAL_OK)
+ return 0;
+ aTxBuffer[count++] = prompt4D4C(receiveStartByteUart);
+ break;
+ // read min,default,max setting
+ // read settings
+
+
+ case 0x72:
+ memcpy(&aTxBuffer[count], dummyForBootloader, 4);
+ count += 4;
+ aTxBuffer[count++] = prompt4D4C(receiveStartByteUart);
+ break;
+ // write settings
+ case 0x77:
+ aTxBuffer[count++] = prompt4D4C(receiveStartByteUart);
+ break;
+ }
+
+ if(count)
+ {
+ if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBuffer, count,10000)!= HAL_OK)
+ return 0;
+ else
+ return prompt4D4C(receiveStartByteUart);
+ }
+ return 0;
+}
+
+#define BLOCKSIZE 0x1000
+
+HAL_StatusTypeDef receive_uart_large_size(UART_HandleTypeDef *huart, uint8_t *pData, uint32_t Size)
+{
+ uint16_t length_4k_blocks;
+ uint16_t length_4k_remainder;
+ uint32_t temp;
+ HAL_StatusTypeDef result = HAL_OK;
+ uint32_t pDataLocal;
+
+ length_4k_blocks = (uint16_t) (Size / BLOCKSIZE);
+ temp = length_4k_blocks;
+ temp *= BLOCKSIZE;
+ length_4k_remainder = (uint16_t) ( Size - temp);
+
+ pDataLocal = (uint32_t)pData;
+
+
+ while((result == HAL_OK) && length_4k_blocks)
+ {
+ result = HAL_UART_Receive(&UartHandle, (uint8_t *)pDataLocal, BLOCKSIZE , UART_TIMEOUT_LARGE_BLOCK);
+ pDataLocal += BLOCKSIZE;
+ length_4k_blocks--;
+ }
+
+ if((result == HAL_OK) && length_4k_remainder)
+ {
+ result = HAL_UART_Receive(&UartHandle, (uint8_t *)pDataLocal, length_4k_remainder , UART_TIMEOUT_LARGE_BLOCK);
+ }
+ return result;
+}
+
+
+/* for safety reason (memory blocking this code is main and sub */
+
+uint8_t receive_update_data_cpu2(void)
+{
+ uint8_t answer;
+
+ uint8_t* pBuffer = (uint8_t*)getFrame(20);
+ answer = receive_update_data_cpu2_sub(pBuffer);
+ releaseFrame(20,(uint32_t)pBuffer);
+ return answer;
+}
+
+
+uint8_t receive_update_data_cpu2_sub(uint8_t* pBuffer)
+{
+ uint8_t sBuffer[10];
+ uint32_t length, offsetTotal, checksum, checksumCalc;
+ uint8_t id;
+ const uint8_t id_RTE = 0xFE;
+
+ //Get length
+ if(HAL_UART_Receive(&UartHandle, pBuffer, 4,5000)!= HAL_OK) // 58000
+ {
+ return 0;
+ }
+ length = 256 * 256 * 256 * (uint32_t)pBuffer[0] + 256 * 256 * (uint32_t)pBuffer[1] + 256 * (uint32_t)pBuffer[2] + pBuffer[3];
+
+ //Get id
+ if(HAL_UART_Receive(&UartHandle, pBuffer, 4,5000)!= HAL_OK) // 58000
+ {
+ return 0;
+ }
+ id = pBuffer[0];
+ offsetTotal = 256 * 256 * 256 * (uint32_t)pBuffer[0] + 256 * 256 * (uint32_t)pBuffer[1] + 256 * (uint32_t)pBuffer[2] + pBuffer[3];
+
+ // get checksum, bytes are in different order on Dev C++ code!!!
+ if(HAL_UART_Receive(&UartHandle, sBuffer, 4,5000)!= HAL_OK) // 58000
+ {
+ return 0;
+ }
+ checksum = 256 * 256 * 256 * (uint32_t)sBuffer[3] + 256 * 256 * (uint32_t)sBuffer[2] + 256 * (uint32_t)sBuffer[1] + sBuffer[0];
+ checksumCalc = length + offsetTotal;
+
+ // no need to get code if checksum == length is wrong
+ if(checksumCalc != checksum)
+ {
+ return 0;
+ }
+
+ //get Code
+ if(receive_uart_large_size(&UartHandle, pBuffer, length)!= HAL_OK)
+ {
+ return 0;
+ }
+
+ //get Checksum
+ if(HAL_UART_Receive(&UartHandle, sBuffer, 4,5000)!= HAL_OK) // 580000
+ {
+ return 0;
+ }
+ checksum = 256 * 256 * 256 *(uint32_t)sBuffer[0] + 256 * 256 * (uint32_t)sBuffer[1] + 256 * (uint32_t)sBuffer[2] + sBuffer[3];
+// uint32_t checksumCalc = crc32c_checksum(pBuffer, length,0,0);
+ checksumCalc = CRC_CalcBlockCRC((uint32_t*)pBuffer, length/4);
+
+ if(checksum != checksumCalc)
+ {
+ return 0;
+ }
+
+ if(id != id_RTE)
+ {
+ strcpy(display_text,"wrong data.");
+ display_text[255] = 32;
+ return 0;
+ }
+
+ strcpy(display_text," RTE update.");
+ display_text[255] = 32;
+
+ return extCPU2bootloader(pBuffer,length,display_text);
+}
+
+uint8_t receive_update_flex(uint8_t isRTEupdateALLOWED)
+{
+ uint8_t answer;
+
+ uint8_t* pBuffer1 = (uint8_t*)getFrame(20);
+ uint8_t* pBuffer2 = (uint8_t*)getFrame(20);
+
+ answer = receive_update_data_flex(pBuffer1, pBuffer2, isRTEupdateALLOWED);
+
+ releaseFrame(20,(uint32_t)pBuffer1);
+ releaseFrame(20,(uint32_t)pBuffer2);
+
+ return answer;
+}
+
+uint8_t receive_update_data_mainCPU_firmware(void)
+{
+ uint8_t answer;
+
+ uint8_t* pBuffer1 = (uint8_t*)getFrame(20);
+
+ answer = receive_update_data_mainCPU_firmware_subroutine(1, pBuffer1, 0);
+
+ releaseFrame(20,(uint32_t)pBuffer1);
+
+ return answer;
+}
+
+/* multi buffer (long data) not tested yet */
+uint8_t receive_update_data_mainCPU_variable_firmware(void)
+{
+ uint8_t answer;
+
+ uint8_t* pBuffer1 = (uint8_t*)getFrame(20);
+ uint8_t* pBuffer2 = (uint8_t*)getFrame(20);
+
+ answer = receive_update_data_mainCPU_firmware_subroutine(2, pBuffer1, pBuffer2);
+
+ releaseFrame(20,(uint32_t)pBuffer1);
+ releaseFrame(20,(uint32_t)pBuffer2);
+
+ return answer;
+}
+
+uint8_t receive_update_data_flex(uint8_t* pBuffer1, uint8_t* pBuffer2, uint8_t RTEupdateALLOWED)
+{
+ uint8_t sBuffer[10];
+ uint8_t serialBuffer[10];
+ uint32_t length1, length2, lengthCompare, offsetCompare, ByteCompareStatus;
+ uint32_t lengthTotal, offsetTotal;
+ uint32_t checksum, checksumCalc = 0;
+ uint8_t id;
+ const uint8_t id_Region1_firmware = 0xFF;
+ const uint8_t id_RTE = 0xFE;
+ uint8_t textpointer = 0;
+
+ //Get length
+ if(HAL_UART_Receive(&UartHandle, sBuffer, 4,5000)!= HAL_OK) // 58000
+ {
+ return 0;
+ }
+ lengthTotal = 256 * 256 * 256 * (uint32_t)sBuffer[0] + 256 * 256 * (uint32_t)sBuffer[1] + 256 * (uint32_t)sBuffer[2] + sBuffer[3];
+
+ //Get offset and/or id (id is 0xFF for RTE, 0xFE for firmware and offset if var)
+ if(HAL_UART_Receive(&UartHandle, sBuffer, 4,5000)!= HAL_OK) // 58000
+ {
+ return 0;
+ }
+ id = sBuffer[0];
+
+ checksumCalc = 256 * 256 * 256 * (uint32_t)sBuffer[0] + 256 * 256 * (uint32_t)sBuffer[1] + 256 * (uint32_t)sBuffer[2] + sBuffer[3];
+ checksumCalc += lengthTotal;
+ //old, does no longer work because of the fonts: checksumCalc = lengthTotal + offsetTotal;
+
+ if((id != id_Region1_firmware) && (id != id_RTE) && (id != id_FONT) && (id != id_FONT_OLD))
+ {
+ return 0;
+ }
+
+ // neu 110212
+ if(id == id_FONT)
+ offsetTotal = 256 * 256 * 256 * (uint32_t)sBuffer[1] + 256 * 256 * (uint32_t)sBuffer[2] + 256 * (uint32_t)sBuffer[3];
+ else
+ offsetTotal = 256 * 256 * 256 * (uint32_t)sBuffer[0] + 256 * 256 * (uint32_t)sBuffer[1] + 256 * (uint32_t)sBuffer[2] + sBuffer[3];
+
+ // get checksum, bytes are in different order on Dev C++ code!!!
+ if(HAL_UART_Receive(&UartHandle, sBuffer, 4,5000)!= HAL_OK) // 58000
+ {
+ return 0;
+ }
+ checksum = 256 * 256 * 256 * (uint32_t)sBuffer[3] + 256 * 256 * (uint32_t)sBuffer[2] + 256 * (uint32_t)sBuffer[1] + sBuffer[0];
+
+
+ if(checksumCalc != checksum)
+ {
+ uint8_t ptr = 0;
+ strcpy(&display_text[ptr]," checksum error");
+ ptr += 15;
+ strcpy(&display_text[ptr],"\n\r");
+ ptr += 2;
+ ptr += gfx_number_to_string(10,0,&display_text[ptr],checksumCalc);
+ display_text[ptr] = 0;
+ display_text[255] = ptr + 1;
+ return 0xFF;
+ }
+
+ //Get serial (new since 160211)
+ if(HAL_UART_Receive(&UartHandle, serialBuffer, 4,5000)!= HAL_OK)
+ {
+ return 0;
+ }
+
+ if(lengthTotal > 768000)
+ {
+ length1 = 768000;
+ length2 = lengthTotal - length1;
+ }
+ else
+ {
+ length1 = lengthTotal;
+ length2 = 0;
+ }
+
+ if((pBuffer2 == 0) && (length2 != 0))
+ return 0;
+
+ //get Code
+ if(receive_uart_large_size(&UartHandle, pBuffer1, length1)!= HAL_OK)
+ return 0;
+
+ if(length2)
+ if(receive_uart_large_size(&UartHandle, pBuffer2, length2)!= HAL_OK)
+ return 0;
+
+ //get Checksum
+ if(HAL_UART_Receive(&UartHandle, sBuffer, 4,5000)!= HAL_OK) // 58000
+ return 0;
+
+ checksum = 256 * 256 * 256 *(uint32_t)sBuffer[0] + 256 * 256 * (uint32_t)sBuffer[1] + 256 * (uint32_t)sBuffer[2] + sBuffer[3];
+// uint32_t checksumCalc = crc32c_checksum(pBuffer1, length1, pBuffer2, length2);
+ if(length2)
+ checksumCalc = CRC_CalcBlockCRC_moreThan768000((uint32_t*)pBuffer1, (uint32_t*)pBuffer2, lengthTotal/4);
+ else
+ checksumCalc = CRC_CalcBlockCRC((uint32_t*)pBuffer1, length1/4);
+
+ /* check id now */
+ /*
+ if(region == 2)
+ {
+ if((id == id_Region1_firmware) || (id == id_RTE))
+ {
+ strcpy(display_text,"wrong data.");
+ display_text[255] = 32;
+ return 0;
+ }
+ }
+ else
+ {
+ if(id != id_Region1_firmware)
+ {
+ strcpy(display_text,"wrong data.");
+ display_text[255] = 32;
+ return 0;
+ }
+ }
+ */
+ /* test checksum */
+ if(checksum != checksumCalc)
+ {
+ uint8_t ptr = 0;
+ strcpy(&display_text[ptr]," checksum error");
+ ptr += 15;
+ strcpy(&display_text[ptr],"\n\r");
+ display_text[ptr] = 0;
+ display_text[255] = ptr + 1;
+ return 0xFF;
+ }
+
+ if(id == id_Region1_firmware)
+ {
+ uint8_t ptr = 0;
+ display_text[ptr++] = 'V';
+ ptr += gfx_number_to_string(2,0,&display_text[ptr],pBuffer1[0x10000] & 0x1F);
+ display_text[ptr++] = '.';
+ ptr += gfx_number_to_string(2,0,&display_text[ptr],pBuffer1[0x10001] & 0x1F);
+ display_text[ptr++] = '.';
+ ptr += gfx_number_to_string(2,0,&display_text[ptr],pBuffer1[0x10002] & 0x1F);
+ display_text[ptr++] = ' ';
+ if(pBuffer1[0x10003])
+ {
+ strcpy(&display_text[ptr],"beta ");
+ ptr +=5;
+ }
+ strcpy(&display_text[ptr],"\n\rpreparing for install.");
+ ptr += 25;
+ display_text[255] = ptr + 1;
+ }
+ else if(id == id_RTE)
+ {
+ if(RTEupdateALLOWED)
+ {
+ strcpy(display_text," RTE update.\n\r");
+ textpointer = 0;
+ while((display_text[textpointer] != 0) && (textpointer < 50))
+ textpointer++;
+ display_text[255] = textpointer+1;
+ return extCPU2bootloader(pBuffer1,length1,display_text);
+ }
+ else
+ return 0xFF;
+ }
+ else
+ //if(region == 2)
+ {
+ uint8_t ptr = 0;
+ ptr += gfx_number_to_string(7,0,&display_text[ptr],lengthTotal);
+ strcpy(&display_text[ptr]," bytes with ");
+ ptr += 12;
+ ptr += gfx_number_to_string(7,0,&display_text[ptr],offsetTotal);
+ strcpy(&display_text[ptr]," offset");
+ ptr += 7;
+ strcpy(&display_text[ptr],"\n\rpreparing for install.");
+ ptr += 25;
+ display_text[255] = ptr + 1;
+ }
+
+
+ // only non RTE !!
+ uint8_t* pBufferCompare = (uint8_t*)getFrame(20);
+ ByteCompareStatus = 0;
+
+ if(id == id_Region1_firmware)
+ {
+ /* standard firmware limited to 768000 */
+ if(ext_flash_read_firmware(pBufferCompare,4,0) != 0xFFFFFFFF)
+ ext_flash_erase_firmware();
+ ext_flash_write_firmware(pBuffer1, length1);
+ lengthCompare = ext_flash_read_firmware(pBufferCompare,768000,0);
+
+ if(lengthCompare != length1)
+ ByteCompareStatus = 10000;
+ for(int i = 0; i < length1; i++)
+ {
+ if(pBuffer1[0] != pBufferCompare[0])
+ ByteCompareStatus++;
+ }
+ }
+ else
+ //if(region == 2)
+ {
+ /* upper region firmware can be larger (1MB) */
+ if(ext_flash_read_firmware2(0, pBufferCompare,4, 0,0) != 0xFFFFFFFF)
+ ext_flash_erase_firmware2();
+ ext_flash_write_firmware2(offsetTotal, pBuffer1, length1, pBuffer2, length2);
+ lengthCompare = ext_flash_read_firmware2(&offsetCompare, pBufferCompare,768000, 0,768000);
+
+ if(lengthCompare != length1 + length2)
+ ByteCompareStatus = 10000;
+ if(offsetTotal != offsetCompare)
+ ByteCompareStatus += 20000;
+ for(int i = 0; i < length1; i++)
+ {
+ if(pBuffer1[0] != pBufferCompare[0])
+ ByteCompareStatus++;
+ }
+
+ lengthCompare = ext_flash_read_firmware2(0, 0,768000, pBufferCompare,768000);
+ for(int i = 0; i < length2; i++)
+ {
+ if(pBuffer2[0] != pBufferCompare[0])
+ ByteCompareStatus++;
+ }
+ }
+
+ releaseFrame(20,(uint32_t)pBufferCompare);
+
+ if(ByteCompareStatus != 0)
+ {
+ strcpy(&display_text[0],"\n\rcopy error.");
+ display_text[255] = 21;
+ return 0;
+ }
+ else
+ {
+ strcpy(&display_text[0],"\n\rready to install.");
+ display_text[255] = 21;
+ return 1;
+ }
+}
+
+
+uint8_t receive_update_data_mainCPU_firmware_subroutine(uint8_t region, uint8_t* pBuffer1, uint8_t* pBuffer2)
+{
+ uint8_t sBuffer[10];
+ uint32_t length1, length2, lengthCompare, offsetCompare, ByteCompareStatus;
+ uint32_t lengthTotal, offsetTotal, checksum, checksumCalc = 0;
+ uint8_t id;
+
+ //Get length
+ if(HAL_UART_Receive(&UartHandle, sBuffer, 4,5000)!= HAL_OK) // 58000
+ return 0;
+
+ lengthTotal = 256 * 256 * 256 * (uint32_t)sBuffer[0] + 256 * 256 * (uint32_t)sBuffer[1] + 256 * (uint32_t)sBuffer[2] + sBuffer[3];
+
+ //Get offset and/or id (id is 0xFF for RTE, 0xFE for firmware and offset if var)
+ if(HAL_UART_Receive(&UartHandle, sBuffer, 4,5000)!= HAL_OK) // 58000
+ return 0;
+
+ id = sBuffer[0];
+
+ checksumCalc = 256 * 256 * 256 * (uint32_t)sBuffer[0] + 256 * 256 * (uint32_t)sBuffer[1] + 256 * (uint32_t)sBuffer[2] + sBuffer[3];
+ checksumCalc += lengthTotal;
+
+ if((id != id_Region1_firmware) && (id != id_RTE) && (id != id_FONT) && (id != id_FONT_OLD))
+ return 0;
+
+ if(id == id_FONT)
+ offsetTotal = 256 * 256 * 256 * (uint32_t)sBuffer[1] + 256 * 256 * (uint32_t)sBuffer[2] + 256 * (uint32_t)sBuffer[3];
+ // alt, prior to id for font
+ else
+ offsetTotal = 256 * 256 * 256 * (uint32_t)sBuffer[0] + 256 * 256 * (uint32_t)sBuffer[1] + 256 * (uint32_t)sBuffer[2] + sBuffer[3];
+
+ // get checksum, bytes are in different order on Dev C++ code!!!
+ if(HAL_UART_Receive(&UartHandle, sBuffer, 4,5000)!= HAL_OK) // 58000
+ return 0;
+
+ checksum = 256 * 256 * 256 * (uint32_t)sBuffer[3] + 256 * 256 * (uint32_t)sBuffer[2] + 256 * (uint32_t)sBuffer[1] + sBuffer[0];
+
+ //old: checksumCalc = lengthTotal + offsetTotal;
+
+ if(checksumCalc != checksum)
+ {
+ uint8_t ptr = 0;
+ strcpy(&display_text[ptr]," checksum error");
+ ptr += 15;
+ strcpy(&display_text[ptr],"\n\r");
+ ptr += 2;
+ ptr += gfx_number_to_string(10,0,&display_text[ptr],checksumCalc);
+ display_text[ptr] = 0;
+ display_text[255] = ptr + 1;
+ return 0xFF;
+ }
+
+ if(lengthTotal > 768000)
+ {
+ length1 = 768000;
+ length2 = lengthTotal - length1;
+ }
+ else
+ {
+ length1 = lengthTotal;
+ length2 = 0;
+ }
+
+ if((pBuffer2 == 0) && (length2 != 0))
+ return 0;
+
+ //get Code
+ if(receive_uart_large_size(&UartHandle, pBuffer1, length1)!= HAL_OK)
+ return 0;
+
+ if(length2)
+ if(receive_uart_large_size(&UartHandle, pBuffer2, length2)!= HAL_OK)
+ return 0;
+
+ //get Checksum
+ if(HAL_UART_Receive(&UartHandle, sBuffer, 4,5000)!= HAL_OK) // 58000
+ return 0;
+
+ checksum = 256 * 256 * 256 *(uint32_t)sBuffer[0] + 256 * 256 * (uint32_t)sBuffer[1] + 256 * (uint32_t)sBuffer[2] + sBuffer[3];
+// uint32_t checksumCalc = crc32c_checksum(pBuffer1, length1, pBuffer2, length2);
+ if(length2)
+ checksumCalc = CRC_CalcBlockCRC_moreThan768000((uint32_t*)pBuffer1, (uint32_t*)pBuffer2, lengthTotal/4);
+ else
+ checksumCalc = CRC_CalcBlockCRC((uint32_t*)pBuffer1, length1/4);
+
+ /* check id now */
+ if(region == 2)
+ {
+ if((id == id_Region1_firmware) || (id == id_RTE))
+ {
+ strcpy(display_text,"wrong data.");
+ display_text[255] = 32;
+ return 0;
+ }
+ }
+ else
+ {
+ if(id != id_Region1_firmware)
+ {
+ strcpy(display_text,"wrong data.");
+ display_text[255] = 32;
+ return 0;
+ }
+ }
+
+ /* test checksum */
+ if(checksum != checksumCalc)
+ {
+ uint8_t ptr = 0;
+ strcpy(&display_text[ptr]," pruefsummen error");
+ ptr += 15;
+ strcpy(&display_text[ptr],"\n\r");
+ display_text[ptr] = 0;
+ display_text[255] = ptr + 1;
+ return 0xFF;
+ }
+
+ if(region == 2)
+ {
+ uint8_t ptr = 0;
+ ptr += gfx_number_to_string(7,0,&display_text[ptr],lengthTotal);
+ strcpy(&display_text[ptr]," bytes with ");
+ ptr += 12;
+ ptr += gfx_number_to_string(7,0,&display_text[ptr],offsetTotal);
+ strcpy(&display_text[ptr]," offset");
+ ptr += 7;
+ strcpy(&display_text[ptr],"\n\rpreparing for install.");
+ ptr += 25;
+ display_text[255] = ptr + 1;
+
+ }
+ else
+ {
+ uint8_t ptr = 0;
+ display_text[ptr++] = 'V';
+ ptr += gfx_number_to_string(2,0,&display_text[ptr],pBuffer1[0x10000] & 0x1F);
+ display_text[ptr++] = '.';
+ ptr += gfx_number_to_string(2,0,&display_text[ptr],pBuffer1[0x10001] & 0x1F);
+ display_text[ptr++] = '.';
+ ptr += gfx_number_to_string(2,0,&display_text[ptr],pBuffer1[0x10002] & 0x1F);
+ display_text[ptr++] = ' ';
+ if(pBuffer1[0x10003])
+ {
+ strcpy(&display_text[ptr],"beta ");
+ ptr +=5;
+ }
+ strcpy(&display_text[ptr],"\n\rpreparing for install.");
+ ptr += 25;
+ display_text[255] = ptr + 1;
+ }
+
+ uint8_t* pBufferCompare = (uint8_t*)getFrame(20);
+ ByteCompareStatus = 0;
+
+ if(region == 2)
+ {
+ /* upper region firmware can be larger (1MB) */
+ if(ext_flash_read_firmware2(0, pBufferCompare,4, 0,0) != 0xFFFFFFFF)
+ ext_flash_erase_firmware2();
+ ext_flash_write_firmware2(offsetTotal, pBuffer1, length1, pBuffer2, length2);
+ lengthCompare = ext_flash_read_firmware2(&offsetCompare, pBufferCompare,768000, 0,768000);
+
+ if(lengthCompare != length1 + length2)
+ ByteCompareStatus = 10000;
+ if(offsetTotal != offsetCompare)
+ ByteCompareStatus += 20000;
+ for(int i = 0; i < length1; i++)
+ {
+ if(pBuffer1[0] != pBufferCompare[0])
+ ByteCompareStatus++;
+ }
+
+ lengthCompare = ext_flash_read_firmware2(0, 0,768000, pBufferCompare,768000);
+ for(int i = 0; i < length2; i++)
+ {
+ if(pBuffer2[0] != pBufferCompare[0])
+ ByteCompareStatus++;
+ }
+ }
+ else
+ {
+ /* standard firmware limited to 768000 */
+ if(ext_flash_read_firmware(pBufferCompare,4,0) != 0xFFFFFFFF)
+ ext_flash_erase_firmware();
+ ext_flash_write_firmware(pBuffer1, length1);
+ lengthCompare = ext_flash_read_firmware(pBufferCompare,768000,0);
+
+ if(lengthCompare != length1)
+ ByteCompareStatus = 10000;
+ for(int i = 0; i < length1; i++)
+ {
+ if(pBuffer1[0] != pBufferCompare[0])
+ ByteCompareStatus++;
+ }
+ }
+
+ releaseFrame(20,(uint32_t)pBufferCompare);
+
+ if(ByteCompareStatus != 0)
+ {
+ strcpy(&display_text[0],"\n\rcopy error.");
+ display_text[255] = 21;
+ return 0;
+ }
+ else
+ {
+ strcpy(&display_text[0],"\n\rready to install.");
+ display_text[255] = 21;
+ return 1;
+ }
+}
+
+void tComm_RequestBluetoothStrength(void)
+{
+ EvaluateBluetoothSignalStrength = 1;
+}
+
+/* read, validate the modul answer and flush rx que if necessary */
+uint8_t tComm_CheckAnswerOK()
+{
+ char answerOkay[] = "\r\nOK\r\n";
+ char aRxBuffer[UART_CMD_BUF_SIZE];
+ uint8_t sizeAnswer = sizeof(answerOkay) -1;
+ uint8_t result = HAL_OK;
+ uint8_t indexRef = 0;
+ uint8_t indexBuf = 0;
+ uint8_t answer;
+
+ memset(aRxBuffer,0,UART_CMD_BUF_SIZE);
+ if(HAL_UART_Receive(&UartHandle, (uint8_t*)aRxBuffer, sizeAnswer, UART_OPERATION_TIMEOUT) == HAL_OK)
+ {
+ do
+ {
+ if(answerOkay[indexRef] == aRxBuffer[indexBuf])
+ {
+ indexRef++;
+ }
+ else
+ {
+ if(indexRef != 0)
+ {
+ indexRef = 0;
+ }
+ }
+ indexBuf++;
+ }while(indexBuf < sizeAnswer);
+
+ if(indexRef != sizeAnswer) /* unexpected answer => there might be characters left in RX que => read and check all rx bytes */
+ {
+ do
+ {
+ answer = HAL_ERROR;
+ if (indexBuf < UART_CMD_BUF_SIZE)
+ {
+ answer = HAL_UART_Receive(&UartHandle, (uint8_t*)&aRxBuffer[indexBuf], 1, 10);
+
+ if(answerOkay[indexRef] == aRxBuffer[indexBuf])
+ {
+ indexRef++;
+ }
+ else
+ {
+ if(indexRef != 0)
+ {
+ indexRef = 0;
+ }
+ }
+ indexBuf++;
+ }
+ }while((answer == HAL_OK) && (indexRef != sizeAnswer));
+ if(indexRef != sizeAnswer)
+ {
+ result = HAL_ERROR;
+ }
+ }
+ }
+ else
+ {
+ result = HAL_ERROR;
+ }
+ return result;
+
+}
+
+
+void tComm_EvaluateBluetoothStrength(void)
+{
+ char aTxBufferBarSSI[] = "AT+BARSSI\r";
+ char aTxBufferEscapeSequence[] = "+++";
+ char aTxBufferEnd[] = "ATO\r";
+ uint8_t sizeRequest = sizeof(aTxBufferBarSSI) -1;
+
+ uint8_t answer = HAL_OK;
+ char aRxBuffer[UART_CMD_BUF_SIZE];
+ char SignalStr[UART_CMD_BUF_SIZE];
+ uint8_t index = 0;
+ uint8_t strindex = 0;
+ int8_t sigqual = 0;
+
+ HAL_Delay(200);
+ if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBufferEscapeSequence, 3, 2000)== HAL_OK)
+ {
+ if(tComm_CheckAnswerOK() == HAL_OK)
+ {
+ HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBufferBarSSI,sizeRequest , 2000);
+ {
+ index = 0;
+ do /* Answer is not the common one. Instead the signal strength is received => read all available bytes one by one*/
+ {
+ answer = HAL_UART_Receive(&UartHandle, (uint8_t*)&aRxBuffer[index], 1, 100);
+ if(index < UART_CMD_BUF_SIZE)
+ {
+ index++;
+ }
+ }while(answer == HAL_OK);
+
+ if((aRxBuffer[index] != 'E') && (aRxBuffer[index] != 0)) /* E represents the first letter of the string ERROR */
+ {
+ index = 0;
+ strindex = 0;
+ do
+ {
+ SignalStr[strindex++] = aRxBuffer[index++];
+ }while ((index < UART_CMD_BUF_SIZE - 1) && (aRxBuffer[index] != '\r'));
+ SignalStr[strindex] = 0; /* terminate String */
+ sigqual = strtol(SignalStr,NULL,0);
+ /* Map db to abstract Bargraph */
+ if(sigqual > 0)
+ {
+ sprintf(SignalStr,"Bluetooth ||||||||");
+ }
+ else
+ {
+ sprintf(SignalStr,"Bluetooth |");
+ strindex = strlen(SignalStr);
+ sigqual *=-1;
+ sigqual = 100 - sigqual; /* invert because of negative db value */
+ while(sigqual / 10 > 0 )
+ {
+ SignalStr[strindex++] = '|';
+ sigqual -= 10;
+ }
+ SignalStr[strindex] = 0;
+ }
+ strcpy(display_text,SignalStr);
+ display_text[255] = strlen(SignalStr);
+ EvaluateBluetoothSignalStrength = 0;
+ }
+ }
+ HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBufferEnd, 4, 2000); /* exit terminal mode */
+ index = 0;
+ do /* module will answer with current connection state */
+ {
+ answer = HAL_UART_Receive(&UartHandle, (uint8_t*)&aRxBuffer[index], 1, 100);
+ if(index < UART_CMD_BUF_SIZE)
+ {
+ index++;
+ }
+ }while(answer == HAL_OK);
+ }
+ }
+}
+
+
+void tComm_StartBlueModBaseInit()
+{
+ BmTmpConfig = BM_INIT_TRIGGER_ON;
+}
+
+
+uint8_t tComm_GetBTCmdStr(BTCmd cmdId, char* pCmdStr)
+{
+ uint8_t ret = 0;
+
+ switch (cmdId)
+ {
+ case BT_CMD_ECHO: sprintf(pCmdStr,"ATE0\r");
+ ret = 1;
+ break;
+ case BT_CMD_BAUDRATE_115: strcpy(pCmdStr,"AT+UMRS=115200,1,8,1,1,1\r");
+ ret = 1;
+ break;
+
+ case BT_CMD_BAUDRATE_460: strcpy(pCmdStr,"AT+UMRS=460800,1,8,1,1,1\r");
+ ret = 1;
+ break;
+ case BT_CMD_NAME: strcpy(pCmdStr,"AT+UBTLN=OSTC5-12345\r");
+ ret = 1;
+ break;
+ case BT_CMD_EXIT_CMD: strcpy(pCmdStr,"ATO1\r");
+ ret = 1;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+void tComm_StartBlueModConfig()
+{
+ uint8_t answer = HAL_OK;
+ uint8_t RxBuffer[UART_CMD_BUF_SIZE];
+ uint8_t index = 0;
+
+ BmTmpConfig = BM_CONFIG_ECHO;
+ do /* flush RX buffer */
+ {
+ answer = HAL_UART_Receive(&UartHandle, (uint8_t*)&RxBuffer[index], 1, 10);
+ if(index < UART_CMD_BUF_SIZE) index++;
+ }while(answer == HAL_OK);
+}
+
+uint8_t tComm_HandleBlueModConfig()
+{
+ static uint8_t RestartModule = 1; /* used to do power off / on cycle */
+ static uint8_t ConfigRetryCnt = 0; /* Retry count without power cycle */
+
+ char TxBuffer[UART_CMD_BUF_SIZE];
+ uint8_t CmdSize = 0;
+
+ uint8_t result = HAL_OK;
+
+ memset(TxBuffer, 0, sizeof(TxBuffer));
+
+ switch (BmTmpConfig)
+ {
+ case BM_CONFIG_ECHO: tComm_GetBTCmdStr (BT_CMD_ECHO, TxBuffer);
+ break;
+ case BM_CONFIG_SILENCE: tComm_GetBTCmdStr (BT_CMD_SILENCE, TxBuffer);
+ break;
+ case BM_CONFIG_ESCAPE_DELAY: tComm_GetBTCmdStr (BT_CMD_ESCAPE_DELAY, TxBuffer);
+ break;
+ case BM_CONFIG_SIGNAL_POLL: tComm_GetBTCmdStr(BT_CMD_SIGNAL_POLL, TxBuffer);
+ break;
+ case BM_CONFIG_BAUD:
+#ifdef ENABLE_FAST_COMM
+ tComm_GetBTCmdStr(BT_CMD_BAUDRATE_460, TxBuffer);
+#else
+ BmTmpConfig = BM_CONFIG_DONE;
+#endif
+ break;
+ case BM_CONFIG_RETRY: ConfigRetryCnt--;
+ HAL_Delay(1);
+ if(ConfigRetryCnt == 0)
+ {
+ MX_Bluetooth_PowerOn();
+ tComm_StartBlueModConfig();
+ }
+ break;
+ case BM_CONFIG_DONE:
+ case BM_CONFIG_OFF:
+ ConfigRetryCnt = 0;
+ RestartModule = 1;
+ break;
+/* the procedure below is just needed for the initial bluetooth module initialization */
+ case BM_INIT_TRIGGER_ON: HAL_Delay(2000);
+ HAL_GPIO_WritePin(BLE_UBLOX_DSR_GPIO_PORT,BLE_UBLOX_DSR_PIN,GPIO_PIN_RESET);
+ BmTmpConfig++;
+ break;
+ case BM_INIT_TRIGGER_OFF: HAL_Delay(1);
+ HAL_GPIO_WritePin(BLE_UBLOX_DSR_GPIO_PORT,BLE_UBLOX_DSR_PIN,GPIO_PIN_SET);
+ HAL_Delay(2000);
+ BmTmpConfig++;
+ break;
+ case BM_INIT_ECHO: sprintf(TxBuffer,"ATE0\r");
+ break;
+ case BM_INIT_FACTORY: sprintf(TxBuffer,"AT+UFACTORY\r"); /*Set to factory defined configuration */
+ break;
+ case BM_INIT_MODE: sprintf(TxBuffer,"AT+UMSM=1\r"); /* start in Data mode */
+ break;
+ case BM_INIT_BLE: sprintf(TxBuffer,"AT+UBTLE=2\r"); /* Bluetooth low energy Peripheral */
+ break;
+ case BM_INIT_NAME: sprintf(TxBuffer,"AT+UBTLN=OSTC5-12345\r"); /* Bluetooth name */
+ if(hardwareDataGetPointer()->primarySerial != 0xFFFF) /* module reinit? => restore old name */
+ {
+ gfx_number_to_string(5,1,&TxBuffer[15],hardwareDataGetPointer()->primarySerial);
+ }
+ break;
+ case BM_INIT_SSP_IDO_OFF: sprintf(TxBuffer,"AT+UDSC=0,0\r"); /* Disable SPP Server on ID0 */
+ break;
+ case BM_INIT_SSP_IDO_ON: sprintf(TxBuffer,"AT+UDSC=0,3\r"); /* SPP Server on ID0 */
+ break;
+ case BM_INIT_SSP_ID1_OFF: sprintf(TxBuffer,"AT+UDSC=1,0\r"); /* Disable SPS Server on ID1 */
+ break;
+ case BM_INIT_SSP_ID1_ON: sprintf(TxBuffer,"AT+UDSC=1,6\r"); /* SPS Server on ID1 */
+ break;
+ case BM_INIT_STORE: sprintf(TxBuffer,"AT&W\r"); /* write settings into eeprom */
+ break;
+ case BM_INIT_RESTART: sprintf(TxBuffer,"AT+CPWROFF\r"); /* reboot module */
+ break;
+ case BM_INIT_DONE: BmTmpConfig = BM_CONFIG_ECHO;
+ break;
+ default:
+ break;
+ }
+ if(TxBuffer[0] != 0) /* forward command to module */
+ {
+ CmdSize = strlen(TxBuffer);
+ if(HAL_UART_Transmit(&UartHandle, (uint8_t*)TxBuffer,CmdSize, 2000) == HAL_OK)
+ {
+ result = tComm_CheckAnswerOK();
+
+ if((BmTmpConfig == BM_CONFIG_BAUD) && (result == HAL_OK) && (UartHandle.Init.BaudRate != 460800)) /* is com already switched to fast speed? */
+ {
+ HAL_UART_DeInit(&UartHandle);
+ HAL_Delay(1);
+ UartHandle.Init.BaudRate = 460800;
+ HAL_UART_Init(&UartHandle);
+ }
+ else if((BmTmpConfig == BM_CONFIG_BAUD) && (result == HAL_OK) && (UartHandle.Init.BaudRate == 460800)) /* This shut not happen because default speed is 115200 => update module configuration */
+ {
+ tComm_GetBTCmdStr(BT_CMD_BAUDRATE_115, TxBuffer);
+
+ CmdSize = strlen(TxBuffer);
+ HAL_UART_Transmit(&UartHandle, (uint8_t*)TxBuffer,CmdSize, 2000);
+ HAL_UART_DeInit(&UartHandle);
+ HAL_Delay(10);
+ UartHandle.Init.BaudRate = 115200;
+ HAL_UART_Init(&UartHandle);
+ sprintf(TxBuffer,"AT&W\r"); /* write configuration */
+ CmdSize = strlen(TxBuffer);
+ HAL_UART_Transmit(&UartHandle, (uint8_t*)TxBuffer,CmdSize, 2000);
+ }
+ if(result == HAL_OK)
+ {
+ BmTmpConfig++;
+ if(BmTmpConfig == BM_CONFIG_RETRY)
+ {
+ BmTmpConfig = BM_CONFIG_DONE;
+ }
+ }
+ if(BmTmpConfig == BM_CONFIG_ECHO)
+ {
+ BmTmpConfig = BM_CONFIG_DONE;
+ ConfigRetryCnt = 0;
+ RestartModule = 1;
+ }
+ }
+ }
+ else /* no command for the configuration step found => skip step */
+ {
+ if((BmTmpConfig > BM_CONFIG_OFF) && (BmTmpConfig < BM_CONFIG_DONE))
+ {
+ BmTmpConfig++;
+ }
+ }
+ if(result != HAL_OK)
+ {
+ ConfigRetryCnt++;
+ if(ConfigRetryCnt > 3) /* Configuration failed => switch off module */
+ {
+ MX_Bluetooth_PowerOff();
+ if(RestartModule)
+ {
+ RestartModule = 0; /* only one try */
+ ConfigRetryCnt = 200; /* used for delay to startup module again */
+
+ if((BmTmpConfig == BM_CONFIG_ECHO) || (BmTmpConfig == BM_INIT_ECHO)) /* the module did not answer even once => try again with alternative baud rate */
+ {
+ HAL_UART_DeInit(&UartHandle);
+ HAL_Delay(1);
+ UartHandle.Init.BaudRate = 460800;
+ HAL_UART_Init(&UartHandle);
+ }
+ BmTmpConfig = BM_CONFIG_RETRY;
+ }
+ else /* even restarting module failed => switch bluetooth off */
+ {
+ ConfigRetryCnt = 0;
+ BmTmpConfig = BM_CONFIG_OFF;
+ }
+ }
+ }
+ return result;
+}
+
+static void tComm_Error_Handler(void)
+{
+ while(1)
+ {}
+}