diff --git a/main/config.h b/main/config.h index 5af80f6..b895eef 100644 --- a/main/config.h +++ b/main/config.h @@ -5,21 +5,21 @@ #define DEFAULT_FreqPlan 0 // #define WITH_HELTEC // HELTEC module: PCB LED on GPI025 -// #define WITH_TTGO // TTGO module: PCB LED on GPIO2, GPIO25 free to use as DAC2 output -#define WITH_TBEAM // T-Beam module +#define WITH_TTGO // TTGO module: PCB LED on GPIO2, GPIO25 free to use as DAC2 output +// #define WITH_TBEAM // T-Beam module // #define WITH_FollowMe // by Avionix #define WITH_RFM95 // #define WITH_RFM69 -// #define WITH_OLED // OLED display on the I2C: some TTGO modules are without OLED display +#define WITH_OLED // OLED display on the I2C: some TTGO modules are without OLED display // #define WITH_OLED2 // 2nd OLED display, I2C address next higher // #define WITH_LED_RX // #define WITH_LED_TX // #define WITH_GPS_ENABLE // use GPS_ENABLE control line to turn the GPS ON/OFF -// #define WITH_GPS_PPS // use the PPS signal from GPS for precise time-sync. +#define WITH_GPS_PPS // use the PPS signal from GPS for precise time-sync. #define WITH_GPS_CONFIG // attempt to configure higher GPS baud rate and airborne mode #define WITH_GPS_UBX // GPS understands UBX // #define WITH_GPS_MTK // GPS understands MTK @@ -31,7 +31,7 @@ // #define WITH_BMP180 // BMP180 pressure sensor // #define WITH_BMP280 // BMP280 pressure sensor -#define WITH_BME280 // BMP280 with humidity (but still works with BMP280) +// #define WITH_BME280 // BMP280 with humidity (but still works with BMP280) // #define WITH_MS5607 // MS5607 pressure sensor #define WITH_PFLAA // PFLAU and PFLAA for compatibility with XCsoar and LK8000 @@ -41,8 +41,8 @@ // #define WITH_BEEPER // #define WITH_SD // use the SD card in SPI mode and FAT file system -#define WITH_SPIFFS // use SPIFFS file system in Flash -#define WITH_LOG // log own positions and other received to SPIFFS and possibly to uSD +// #define WITH_SPIFFS // use SPIFFS file system in Flash +// #define WITH_LOG // log own positions and other received to SPIFFS and possibly to uSD #define WITH_BT_SPP // Bluetooth serial port for smartphone/tablet link // #define WITH_WIFI // attempt to connect to the wifi router for uploading the log files diff --git a/main/ctrl.cpp b/main/ctrl.cpp index 0b4b992..3abc186 100644 --- a/main/ctrl.cpp +++ b/main/ctrl.cpp @@ -98,6 +98,92 @@ int OLED_DisplayPosition(GPS_Position *GPS=0, uint8_t LineIdx=2) return 0; } #endif +#ifdef WITH_U8G2 + +void OLED_PutLine(u8g2_t *OLED, uint8_t LineIdx, const char *Line) +{ if(Line==0) return; +#ifdef DEBUG_PRINT + xSemaphoreTake(CONS_Mutex, portMAX_DELAY); + Format_String(CONS_UART_Write, "OLED_PutLine( ,"); + Format_UnsDec(CONS_UART_Write, (uint16_t)LineIdx); + CONS_UART_Write(','); + Format_String(CONS_UART_Write, Line); + Format_String(CONS_UART_Write, ")\n"); + xSemaphoreGive(CONS_Mutex); +#endif + // u8g2_SetFont(OLED, u8g2_font_5x8_tr); + u8g2_SetFont(OLED, u8g2_font_amstrad_cpc_extended_8r); + u8g2_DrawStr(OLED, 0, (LineIdx+1)*8, Line); +} + +void OLED_DrawStatus(u8g2_t *OLED, uint32_t Time, uint8_t LineIdx=0) +{ char Line[32]; + Format_String(Line , "OGN Tx/Rx "); + Format_HHMMSS(Line+10, Time); Line[16]=0; + OLED_PutLine(OLED, LineIdx++, Line); + Parameters.Print(Line); Line[16]=0; + OLED_PutLine(OLED, LineIdx++, Line); } + +void OLED_DrawPosition(u8g2_t *OLED, GPS_Position *GPS=0, uint8_t LineIdx=2) +{ char Line[20]; + if(GPS && GPS->isValid()) + { Line[0]=' '; + Format_SignDec(Line+1, GPS->Latitude /60, 6, 4); Line[9]=' '; + Format_UnsDec (Line+10, GPS->Altitude /10, 5, 0); Line[15]='m'; + OLED_PutLine(OLED, LineIdx , Line); + Format_SignDec(Line, GPS->Longitude/60, 7, 4); + Format_SignDec(Line+10, GPS->ClimbRate, 4, 1); + OLED_PutLine(OLED, LineIdx+1, Line); + Format_UnsDec (Line , GPS->Speed, 4, 1); Format_String(Line+5, "m/s "); + Format_UnsDec (Line+10, GPS->Heading, 4, 1); Line[15]='^'; + OLED_PutLine(OLED, LineIdx+2, Line); + Format_String(Line, "0D/00sat DOP00.0"); + Line[0]+=GPS->FixMode; Format_UnsDec(Line+3, GPS->Satellites, 2); + Format_UnsDec(Line+12, (uint16_t)GPS->HDOP, 3, 1); + OLED_PutLine(OLED, LineIdx+3, Line); + } + // else { OLED_PutLine(OLED, LineIdx, 0); OLED_PutLine(OLED, LineIdx+1, 0); OLED_PutLine(LineIdx+2, 0); OLED_PutLine(LineIdx+3, 0); } + if(GPS && GPS->isDateValid()) + { Format_UnsDec (Line , (uint16_t)GPS->Day, 2, 0); Line[2]='.'; + Format_UnsDec (Line+ 3, (uint16_t)GPS->Month, 2, 0); Line[5]='.'; + Format_UnsDec (Line+ 6, (uint16_t)GPS->Year , 2, 0); Line[8]=' '; Line[9]=' '; } + else Format_String(Line, " "); + if(GPS && GPS->isTimeValid()) + { Format_UnsDec (Line+10, (uint16_t)GPS->Hour, 2, 0); + Format_UnsDec (Line+12, (uint16_t)GPS->Min, 2, 0); + Format_UnsDec (Line+14, (uint16_t)GPS->Sec, 2, 0); + } else Line[10]=0; + OLED_PutLine(OLED, LineIdx+4, Line); + Line[0]=0; + if(GPS && GPS->hasBaro) + { Format_String(Line , "0000.0hPa 00000m"); + Format_UnsDec(Line , GPS->Pressure/40, 5, 1); + Format_UnsDec(Line+10, GPS->StdAltitude/10, 5, 0); } + OLED_PutLine(OLED, LineIdx+5, Line); +} + +void OLED_DrawGPS(u8g2_t *OLED) +{ u8g2_SetFont(OLED, u8g2_font_ncenB14_tr); + u8g2_DrawStr(OLED, 0, 16, "GPS"); +} + +void OLED_DrawRF(u8g2_t *OLED) +{ u8g2_SetFont(OLED, u8g2_font_ncenB14_tr); + u8g2_DrawStr(OLED, 0, 16, "RF"); +} + +void OLED_DrawBARO(u8g2_t *OLED) +{ u8g2_SetFont(OLED, u8g2_font_ncenB14_tr); + u8g2_DrawStr(OLED, 0, 16, "Baro"); +} + +void OLED_DrawSYS(u8g2_t *OLED) +{ u8g2_SetFont(OLED, u8g2_font_ncenB14_tr); + u8g2_DrawStr(OLED, 0, 16, "SYS"); +} + +#endif + // ======================================================================================================================== static NMEA_RxMsg NMEA; @@ -219,9 +305,10 @@ static void ProcessCtrlC(void) // print system Format_String(CONS_UART_Write, "kB total, "); } Format_UnsDec(CONS_UART_Write, Files); Format_String(CONS_UART_Write, " files\n"); +#endif // WITH_SPIFFS + Parameters.Write(CONS_UART_Write); // write the parameters to the console // Parameters.WriteFile(stdout); // write the parameters to the stdout -#endif // WITH_SPIFFS #ifdef WITH_SD Format_String(CONS_UART_Write, "SD card:"); @@ -245,8 +332,6 @@ static void ProcessCtrlL(void) // print syste #endif } - - static void ProcessInput(void) { for( ; ; ) { uint8_t Byte; int Err=CONS_UART_Read(Byte); if(Err<=0) break; // get byte from console, if none: exit the loop @@ -275,6 +360,9 @@ static void ProcessInput(void) // ======================================================================================================================== +const uint8_t OLED_Pages = 5; +static uint8_t OLED_Page=0; + extern "C" void vTaskCTRL(void* pvParameters) { uint32_t PrevTime=0; @@ -286,8 +374,23 @@ void vTaskCTRL(void* pvParameters) LED_TimerCheck(1); // update the LED flashes #ifdef WITH_BEEPER - Play_TimerCheck(); // update the LED flashes + Play_TimerCheck(1); // read the button(s) #endif + bool PageChange=0; + int32_t PressRelease=Button_TimerCheck(); + if(PressRelease!=0) + { xSemaphoreTake(CONS_Mutex, portMAX_DELAY); + Format_String(CONS_UART_Write, "PressRelease = "); + Format_SignDec(CONS_UART_Write, PressRelease); + Format_String(CONS_UART_Write, "ms\n"); + xSemaphoreGive(CONS_Mutex); } + if(PressRelease>0) + { if(PressRelease<=300) // short button push: switch pages + { OLED_Page++; if(OLED_Page>=OLED_Pages) OLED_Page=0; + PageChange=1; } + else if(PressRelease<=2000) // long button push: some page action + { } + } uint32_t Time=TimeSync_Time(); GPS_Position *GPS = GPS_getPosition(); @@ -297,12 +400,16 @@ void vTaskCTRL(void* pvParameters) PrevTime=Time; PrevGPS=GPS; #ifdef WITH_OLED - esp_err_t StatErr=ESP_OK; - esp_err_t PosErr=ESP_OK; - if(TimeChange) - { StatErr = OLED_DisplayStatus(Time, 0); } - if(GPSchange) - { PosErr = OLED_DisplayPosition(GPS, 2); } + if(Button_SleepRequest) + { OLED_DisplayON(0); } + else + { esp_err_t StatErr=ESP_OK; + esp_err_t PosErr=ESP_OK; + if(TimeChange) + { StatErr = OLED_DisplayStatus(Time, 0); } + if(GPSchange) + { PosErr = OLED_DisplayPosition(GPS, 2); } + } #ifdef DEBUG_PRINT xSemaphoreTake(CONS_Mutex, portMAX_DELAY); if(TimeChange) @@ -317,6 +424,24 @@ void vTaskCTRL(void* pvParameters) #endif #endif // WITH_OLED +#ifdef WITH_U8G2 + if(Button_SleepRequest) + { u8g2_SetPowerSave(&U8G2_OLED, 0); } + else if(TimeChange || PageChange) + { u8g2_ClearBuffer(&U8G2_OLED); + switch(OLED_Page) + { case 1: OLED_DrawGPS(&U8G2_OLED); break; + case 2: OLED_DrawRF(&U8G2_OLED); break; + case 3: OLED_DrawBARO(&U8G2_OLED); break; + case 4: OLED_DrawSYS(&U8G2_OLED); break; + default: + { OLED_DrawStatus(&U8G2_OLED, Time, 0); + OLED_DrawPosition(&U8G2_OLED, GPS, 2); } + } + u8g2_SendBuffer(&U8G2_OLED); + } +#endif + #ifdef DEBUG_PRINT // in debug mode print the parameters and state every 60sec if((Time%60)!=0) continue; ProcessCtrlC(); diff --git a/main/gps.cpp b/main/gps.cpp index 8847995..77f1911 100644 --- a/main/gps.cpp +++ b/main/gps.cpp @@ -404,6 +404,15 @@ static void GPS_NMEA(void) // wh if(NMEA.isGxRMC()) GPS_Burst.GxRMC=1; if(NMEA.isGxGGA()) GPS_Burst.GxGGA=1; if(NMEA.isGxGSA()) GPS_Burst.GxGSA=1; + if(Button_SleepRequest) + { +#ifdef WITH_GPS_MTK +#ifdef WITH_GPS_ENABLE + GPS_DISABLE(); +#endif + Format_String(GPS_UART_Write, /* "$PMTK161,0*28\r\n", */ "$PMTK225,4*2F\r\n", 15, 0); // 225 or "$PMTK161,0*28\r\n" request to the GPS to enter sleep +#endif + } #ifdef DEBUG_PRINT xSemaphoreTake(CONS_Mutex, portMAX_DELAY); Format_UnsDec(CONS_UART_Write, TimeSync_Time()%60); @@ -845,5 +854,3 @@ void vTaskGPS(void* pvParameters) } } } - - diff --git a/main/hal.cpp b/main/hal.cpp index 15ab4b2..27354f2 100644 --- a/main/hal.cpp +++ b/main/hal.cpp @@ -48,6 +48,10 @@ #include "font8x8_basic.h" #endif +#ifdef WITH_U8G2 +#include "u8g2.h" +#endif + // ====================================================================================================== /* The HELTEC AUtomation board WiFi LoRa 32 with sx1278 (RFM95) @@ -123,11 +127,11 @@ PSRM32 = SDIO ? GPIO HELTEC TTGO JACEK T-Beam FollowMe Restrictions - 0 . + 0 Button 1 CONS/TxD CONS/TxD CONS/TxD CONS/TxD Console/Program - 2 SD/MISO . IO02 Bootstrap: LOW to enter UART download mode + 2 SD/MISO . LED Bootstrap: LOW to enter UART download mode 3 CONS/RxD CONS/RxD CONS/RxD CONS/RxD Console/Program - 4 OLED/SDA OLED/SDA ADC/CS Beeper GPS/RST + 4 OLED/SDA OLED/SDA ADC/CS Beeper PER/RST 5 RF/SCK RF/SCK RF/SCK RF/SCK RF/CS 6 SD/CLK 7 SD/DATA0 @@ -135,10 +139,10 @@ GPIO HELTEC TTGO JACEK T-Beam FollowMe Restrictions 9 SD/DATA2 10 SD/DATA3 11 SD/CMD -12 GPS/RxD GPS/RxD SD/CS GPS/RxD IO12 JTAG/TDI Bootstrap: select output voltage to power the flash chip -13 GPS/Ena GPS/Ena SD/SCK IO13 JTAG/TCK -14 RF/RST RF/RST Beeper LED IO14 JTAG/TMS -15 OLED/SCL OLED/SCL SD/MOSI GPS/TxD IO15 JTAG/TDO +12 GPS/RxD GPS/RxD SD/CS GPS/RxD SD/MISO JTAG/TDI Bootstrap: select output voltage to power the flash chip +13 GPS/Ena GPS/Ena SD/SCK SD/MOSI JTAG/TCK +14 RF/RST RF/RST Beeper LED SD/CLK JTAG/TMS +15 OLED/SCL OLED/SCL SD/MOSI GPS/TxD SD/CS JTAG/TDO 16 OLED/RST OLED/RST RF/IRQ GPS/Tx 17 Beeper Beeper RF/RST GPS/Rx 18 RF/CS RF/CS RF/MISO RF/CS RF/SCK @@ -148,21 +152,21 @@ GPIO HELTEC TTGO JACEK T-Beam FollowMe Restrictions 22 PWR/ON I2C/SCL I2C/CLK 23 PWR/LDO RF/RST RF/MOSI 24 -25 LED DAC2 . . -26 RF/IRQ RF/IRQ SCL RF/IRQ -27 RF/MOSI RF/MOSI SDA +25 LED DAC2 . . TT/RX0 +26 RF/IRQ RF/IRQ SCL RF/IRQ BMX/INT1 +27 RF/MOSI RF/MOSI SDA TT/TX0 28 29 30 31 -32 GPS/TxD . RF/RST -33 OLED/RST . GPS/EN +32 GPS/TxD . TT/BOOT +33 OLED/RST . GPS/WAKE 34 GPS/PPS GPS/PPS GPS/RxD GPS/PPS 35 GPS/TxD GPS/TxD GPS/PPS BAT/Sense RF/IRQ -36 BAT/Sense LED/DBG +36 BAT/Sense BAT/Sense 37 38 -39 LED/TX +39 Button */ @@ -203,7 +207,7 @@ GPIO HELTEC TTGO JACEK T-Beam FollowMe Restrictions #endif // TBEAM #ifdef WITH_FollowMe -#define PIN_RFM_RST GPIO_NUM_32 // Reset +// #define PIN_RFM_RST GPIO_NUM_32 // Reset #define PIN_RFM_IRQ GPIO_NUM_35 // 39 // packet done on receive or transmit #define PIN_RFM_SS GPIO_NUM_5 // SPI chip-select #define PIN_RFM_SCK GPIO_NUM_18 // SPI clock @@ -234,7 +238,8 @@ GPIO HELTEC TTGO JACEK T-Beam FollowMe Restrictions #define PIN_GPS_RXD GPIO_NUM_16 #define PIN_GPS_PPS GPIO_NUM_34 // high active #define PIN_GPS_ENA GPIO_NUM_33 // Enable: high-active -#define PIN_GPS_RST GPIO_NUM_4 // Reset: high-active (inverter to L80 RES input) + +#define PIN_PERIPH_RST GPIO_NUM_4 // Reset: high-active #endif #define CONS_UART UART_NUM_0 // UART0 for the console (the system does this for us) @@ -242,6 +247,12 @@ GPIO HELTEC TTGO JACEK T-Beam FollowMe Restrictions #define I2C_BUS I2C_NUM_1 // use bus #1 to talk to OLED and Baro sensor +#ifdef WITH_FollowMe +#define ADSB_UART UART_NUM_2 // UART2 +#define PIN_ADSB_TXD GPIO_NUM_25 +#define PIN_ADSB_RXD GPIO_NUM_27 +#endif + #if defined(WITH_HELTEC) || defined(WITH_TTGO) #define PIN_I2C_SCL GPIO_NUM_15 // SCL pin #define PIN_I2C_SDA GPIO_NUM_4 // SDA pin @@ -252,13 +263,14 @@ GPIO HELTEC TTGO JACEK T-Beam FollowMe Restrictions #ifdef WITH_TBEAM // T-Beam #define PIN_I2C_SCL GPIO_NUM_22 // SCL pin => this way the pin pattern fits the BMP280 module #define PIN_I2C_SDA GPIO_NUM_21 // SDA pin +#define OLED_I2C_ADDR 0x3C // I2C address of the OLED display #endif #ifdef WITH_FollowMe // #define PIN_I2C_SCL GPIO_NUM_22 // SCL pin #define PIN_I2C_SDA GPIO_NUM_21 // SDA pin #define OLED_I2C_ADDR 0x3C // I2C address of the OLED display -#define PIN_OLED_RST GPIO_NUM_15 // OLED RESET: low-active +// #define PIN_OLED_RST GPIO_NUM_15 // OLED RESET: low-active #endif uint8_t BARO_I2C = (uint8_t)I2C_BUS; @@ -271,7 +283,7 @@ uint8_t BARO_I2C = (uint8_t)I2C_BUS; #define PIN_BEEPER GPIO_NUM_17 #endif -#if !defined(WITH_OLED) && !defined(WITH_BMP180) && !defined(WITH_BMP280) && !defined(WITH_BME280) +#if !defined(WITH_OLED) && !defined(WITH_U8G2) && !defined(WITH_BMP180) && !defined(WITH_BMP280) && !defined(WITH_BME280) #undef PIN_I2C_SCL #undef PIN_I2C_SDA #endif @@ -281,6 +293,12 @@ uint8_t BARO_I2C = (uint8_t)I2C_BUS; #define PIN_SD_SCK GPIO_NUM_14 #define PIN_SD_CS GPIO_NUM_15 +#ifdef WITH_FollowMe +#define PIN_BUTTON GPIO_NUM_39 +#else +#define PIN_BUTTON GPIO_NUM_0 +#endif + // ====================================================================================================== // 48-bit unique ID of the chip @@ -330,6 +348,11 @@ void LED_PCB_On (void) { } void LED_PCB_Off (void) { } #endif +#ifdef PIN_BUTTON +void Button_Dir (void) { gpio_set_direction(PIN_BUTTON, GPIO_MODE_INPUT); } +bool Button_isPressed(void) { return !gpio_get_level(PIN_BUTTON); } +#endif + // ======================================================================================================== // ~/esp-idf/components/bt/bluedroid/api/include/esp_spp_api.h @@ -559,13 +582,24 @@ int CONS_UART_Read (uint8_t &Byte) { int Ret=getchar(); if(Ret>=0) { Byte=Ret // int CONS_UART_Free (void) { return UART2_Free(); } // int CONS_UART_Full (void) { return UART2_Full(); } +//-------------------------------------------------------------------------------------------------------- +// ADS-B UART + +#ifdef ADSB_UART +int ADSB_UART_Read (uint8_t &Byte) { return uart_read_bytes (ADSB_UART, &Byte, 1, 0); } // should be buffered and non-blocking +void ADSB_UART_Write (char Byte) { uart_write_bytes (ADSB_UART, &Byte, 1); } // should be buffered and blocking +void ADSB_UART_SetBaudrate(int BaudRate) { uart_set_baudrate(ADSB_UART, BaudRate); } +#endif + //-------------------------------------------------------------------------------------------------------- // GPS UART +#ifdef GPS_UART // int GPS_UART_Full (void) { size_t Full=0; uart_get_buffered_data_len(GPS_UART, &Full); return Full; } int GPS_UART_Read (uint8_t &Byte) { return uart_read_bytes (GPS_UART, &Byte, 1, 0); } // should be buffered and non-blocking void GPS_UART_Write (char Byte) { uart_write_bytes (GPS_UART, &Byte, 1); } // should be buffered and blocking void GPS_UART_SetBaudrate(int BaudRate) { uart_set_baudrate(GPS_UART, BaudRate); } +#endif #ifdef WITH_GPS_ENABLE void GPS_DISABLE(void) { gpio_set_level(PIN_GPS_ENA, 0); } @@ -718,7 +752,29 @@ esp_err_t OLED_Init(uint8_t DispIdx) i2c_master_write_byte(cmd, 0x14, true); i2c_master_write_byte(cmd, OLED_CMD_SET_SEGMENT_REMAP, true); // reverse left-right mapping i2c_master_write_byte(cmd, OLED_CMD_SET_COM_SCAN_MODE, true); // reverse up-bottom mapping - i2c_master_write_byte(cmd, OLED_CMD_DISPLAY_ON, true); + i2c_master_write_byte(cmd, OLED_CMD_DISPLAY_ON, true); // Turn ON the display + i2c_master_stop(cmd); + esp_err_t espRc = i2c_master_cmd_begin(I2C_BUS, cmd, 10); + i2c_cmd_link_delete(cmd); + return espRc; } + +esp_err_t OLED_DisplayON(uint8_t ON, uint8_t DispIdx) +{ i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, ((OLED_I2C_ADDR+DispIdx)<<1) | I2C_MASTER_WRITE, true); + i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_STREAM, true); + i2c_master_write_byte(cmd, OLED_CMD_DISPLAY_OFF+ON, true); + i2c_master_stop(cmd); + esp_err_t espRc = i2c_master_cmd_begin(I2C_BUS, cmd, 10); + i2c_cmd_link_delete(cmd); + return espRc; } + +esp_err_t OLED_DisplayINV(uint8_t INV, uint8_t DispIdx) +{ i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, ((OLED_I2C_ADDR+DispIdx)<<1) | I2C_MASTER_WRITE, true); + i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_STREAM, true); + i2c_master_write_byte(cmd, OLED_CMD_DISPLAY_NORMAL+INV, true); i2c_master_stop(cmd); esp_err_t espRc = i2c_master_cmd_begin(I2C_BUS, cmd, 10); i2c_cmd_link_delete(cmd); @@ -742,9 +798,9 @@ esp_err_t OLED_PutLine(uint8_t Line, const char *Text, uint8_t DispIdx) i2c_master_start(cmd); i2c_master_write_byte(cmd, ((OLED_I2C_ADDR+DispIdx)<<1) | I2C_MASTER_WRITE, true); i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_STREAM, true); - i2c_master_write_byte(cmd, 0x00, true); - i2c_master_write_byte(cmd, 0x10, true); - i2c_master_write_byte(cmd, 0xB0 | Line, true); + i2c_master_write_byte(cmd, 0x00, true); // 0x0L => column address: Lower nibble + i2c_master_write_byte(cmd, 0x10, true); // 0x1H => column address: Higher nibble + i2c_master_write_byte(cmd, 0xB0 | Line, true); // 0xBP => Page address i2c_master_stop(cmd); esp_err_t espRc = i2c_master_cmd_begin(I2C_BUS, cmd, 10); i2c_cmd_link_delete(cmd); @@ -774,6 +830,163 @@ esp_err_t OLED_Clear(uint8_t DispIdx) return espRc; } #endif +#ifdef WITH_U8G2 + +static i2c_cmd_handle_t U8G2_Cmd; + +static uint8_t u8g2_esp32_i2c_byte_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) +{ +#ifdef DEBUG_PRINT + xSemaphoreTake(CONS_Mutex, portMAX_DELAY); + Format_String(CONS_UART_Write, "u8g2_byte_cb("); + CONS_UART_Write(','); + Format_UnsDec(CONS_UART_Write, (uint16_t)msg); + CONS_UART_Write(','); + Format_UnsDec(CONS_UART_Write, (uint16_t)arg_int); + Format_String(CONS_UART_Write, ") "); +#endif + switch(msg) + { case U8X8_MSG_BYTE_SET_DC: + break; + case U8X8_MSG_BYTE_INIT: + break; + case U8X8_MSG_BYTE_START_TRANSFER: + { U8G2_Cmd=i2c_cmd_link_create(); + uint8_t Addr = u8x8_GetI2CAddress(u8x8); +#ifdef DEBUG_PRINT + Format_Hex(CONS_UART_Write, Addr); +#endif + i2c_master_start(U8G2_Cmd); + i2c_master_write_byte(U8G2_Cmd, (Addr<<1) | I2C_MASTER_WRITE, true); + break; } + case U8X8_MSG_BYTE_SEND: + // { i2c_master_write(U8G2_Cmd, (uint8_t *)arg_ptr, arg_int, true); break; } + { uint8_t* Data = (uint8_t *)arg_ptr; + for( int Idx=0; Idx good, ESP_FAIL => failed to mound the file system, other => HW not working if(Ret!=ESP_OK) SD_Unmount(); - return Ret; } + return Ret; } // ESP_OK => all good, ESP_FAIL => failed to mount file system, other => failed to init. the SD card static esp_err_t SD_Init(void) { @@ -856,6 +1069,84 @@ void LED_TimerCheck(uint8_t Ticks) #endif } +bool Button_SleepRequest = 0; + +uint32_t Button_PressTime=0; // [ms] counts for how long the button is kept pressed +uint32_t Button_ReleaseTime=0; + +const int8_t Button_FilterTime = 20; // [ms] +const int8_t Button_FilterThres = Button_FilterTime/2; +static int8_t Button_Filter=(-Button_FilterTime); + +// void Sleep(void) +// { +// #ifdef PIN_PERIPH_RST +// gpio_set_level(PIN_PERIPH_RST, 0); +// #endif +// #ifdef PIN_GPS_ENA +// gpio_set_level(PIN_GPS_ENA, 0); +// #endif +// esp_light_sleep_start(); +// Button_SleepRequest = 0; +// Button_PressTime=0; +// #ifdef PIN_PERIPH_RST +// gpio_set_level(PIN_PERIPH_RST, 0); +// +// gpio_set_level(PIN_PERIPH_RST, 1); +// #endif +// } + +static uint32_t Button_keptPressed(uint8_t Ticks) +{ uint32_t ReleaseTime=0; + Button_PressTime+=Ticks; + // Button_SleepRequest = Button_PressTime>=30000; // [ms] setup SleepRequest if button pressed for >= 4sec + // if(Button_PressTime>=32000) + // { Format_String(CONS_UART_Write, "Sleep in 2 sec\n"); + // vTaskDelay(2000); + // Sleep(); } + if(Button_ReleaseTime) + { // Format_String(CONS_UART_Write, "Button pressed: released for "); + // Format_UnsDec(CONS_UART_Write, Button_ReleaseTime, 4, 3); + // Format_String(CONS_UART_Write, "sec\n"); + ReleaseTime=Button_ReleaseTime; + Button_ReleaseTime=0; } + return ReleaseTime; } // [ms] when button was pressed, return the release time + +static uint32_t Button_keptReleased(uint8_t Ticks) +{ uint32_t PressTime=0; + Button_ReleaseTime+=Ticks; + if(Button_PressTime) + { // Format_String(CONS_UART_Write, "Button released: pressed for "); + // Format_UnsDec(CONS_UART_Write, Button_PressTime, 4, 3); + // Format_String(CONS_UART_Write, "sec\n"); + // if(Button_SleepRequest) + // { Format_String(CONS_UART_Write, "Sleep in 2 sec\n"); + // vTaskDelay(2000); + // Sleep(); } + PressTime=Button_PressTime; + Button_PressTime=0; + } + return PressTime; } // [ms] when button is released, return the press time + +int32_t Button_TimerCheck(uint8_t Ticks) +{ int32_t PressReleaseTime=0; +#ifdef PIN_BUTTON + // CONS_UART_Write(Button_isPressed()?'^':'_'); + if(Button_isPressed()) + { Button_Filter+=Ticks; if(Button_Filter>Button_FilterTime) Button_Filter=Button_FilterTime; + if(Button_Filter>=Button_FilterThres) + { uint32_t ReleaseTime=Button_keptPressed(Ticks); + if(ReleaseTime) PressReleaseTime=(-(int32_t)ReleaseTime);; } + } + else + { Button_Filter-=Ticks; if(Button_Filter<(-Button_FilterTime)) Button_Filter=(-Button_FilterTime); + if(Button_Filter<=(-Button_FilterThres)) + { uint32_t PressTime=Button_keptReleased(Ticks); + if(PressTime) PressReleaseTime=PressTime; } + } +#endif + return PressReleaseTime; } // [ms] return press (positive) or release (negative) button times + /* extern "C" void vApplicationIdleHook(void) // when RTOS is idle: should call "sleep until an interrupt" @@ -907,6 +1198,9 @@ void IO_Configuration(void) LED_PCB_Dir(); LED_PCB_Off(); #endif +#ifdef PIN_BUTTON + Button_Dir(); +#endif RFM_IRQ_Dir(); RFM_RESET_Dir(); @@ -940,6 +1234,10 @@ void IO_Configuration(void) esp_err_t ret=spi_bus_initialize(RFM_SPI_HOST, &BusCfg, 1); ret=spi_bus_add_device(RFM_SPI_HOST, &DevCfg, &RFM_SPI); +#ifdef PIN_PERIPH_RST + gpio_set_direction(PIN_PERIPH_RST, GPIO_MODE_OUTPUT); + gpio_set_level(PIN_PERIPH_RST, 1); +#endif #ifdef PIN_GPS_PPS gpio_set_direction(PIN_GPS_PPS, GPIO_MODE_INPUT); #endif @@ -949,9 +1247,14 @@ void IO_Configuration(void) #endif #ifdef PIN_GPS_ENA gpio_set_direction(PIN_GPS_ENA, GPIO_MODE_OUTPUT); - gpio_set_level(PIN_GPS_ENA, 1); +#ifdef WITH_GPS_MTK + gpio_set_level(PIN_GPS_ENA, 0); // +#else + gpio_set_level(PIN_GPS_ENA, 1); // +#endif #endif +#ifdef GPS_UART uart_config_t GPS_UART_Config = // GPS UART { baud_rate : 9600, data_bits : UART_DATA_8_BITS, @@ -964,10 +1267,28 @@ void IO_Configuration(void) uart_param_config (GPS_UART, &GPS_UART_Config); uart_set_pin (GPS_UART, PIN_GPS_TXD, PIN_GPS_RXD, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); uart_driver_install(GPS_UART, 256, 256, 0, 0, 0); +#endif -#if defined(WITH_OLED) && defined(PIN_OLED_RST) +#ifdef ADSB_UART + uart_config_t ADSB_UART_Config = // ADSB UART + { baud_rate : 115200, + data_bits : UART_DATA_8_BITS, + parity : UART_PARITY_DISABLE, + stop_bits : UART_STOP_BITS_1, + flow_ctrl : UART_HW_FLOWCTRL_DISABLE, + rx_flow_ctrl_thresh: 0, + use_ref_tick: 0 + }; + uart_param_config (ADSB_UART, &ADSB_UART_Config); + uart_set_pin (ADSB_UART, PIN_ADSB_TXD, PIN_ADSB_RXD, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); + uart_driver_install(ADSB_UART, 256, 256, 0, 0, 0); +#endif + +#if defined(WITH_OLED) || defined(WITH_U8G2) +#ifdef PIN_OLED_RST gpio_set_direction(PIN_OLED_RST, GPIO_MODE_OUTPUT); #endif +#endif #if defined(PIN_I2C_SCL) && defined(PIN_I2C_SDA) i2c_config_t I2C_Config = // I2C for OLED and pressue sensor @@ -999,6 +1320,10 @@ void IO_Configuration(void) #endif #endif +#ifdef WITH_U8G2 + U8G2_Init(); +#endif + #ifdef WITH_SD SD_Init(); #endif @@ -1010,6 +1335,7 @@ void IO_Configuration(void) ADC_Init(); // esp_register_freertos_tick_hook(&vApplicationTickHook); + } // ====================================================================================================== diff --git a/main/hal.h b/main/hal.h index 51ce1da..45cec6c 100644 --- a/main/hal.h +++ b/main/hal.h @@ -19,63 +19,17 @@ #define HARDWARE_ID 0x02 #define SOFTWARE_ID 0x01 -// #define DEFAULT_AcftType 1 // [0..15] default aircraft-type: glider -// #define DEFAULT_GeoidSepar 40 // [m] -// #define DEFAULT_CONbaud 115200 -// #define DEFAULT_PPSdelay 80 - #define USE_BLOCK_SPI // use block SPI interface for RF chip #define I2C_SPEED 1000000 // [Hz] bit rate on the I2C (nominally up to 400000) -// #define WITH_HELTEC // HELTEC module: PCB LED on GPI025 -// #define WITH_TTGO // TTGO module: PCB LED on GPIO2, GPIO25 free to use as DAC2 output -// #define WITH_TBEAM // T-Beam module -// #define WITH_JACEK // JACEK ESP32 OGN-Tracker - -// #define WITH_OLED // OLED display on the I2C: some TTGO modules are without OLED display -// #define WITH_OLED2 // 2nd OLED display, I2C address next higher - -// #define WITH_RFM95 // RF chip selection: both HELTEC and TTGO use sx1276 which is same af RFM95 -// #define WITH_RFM69 // Jacek design uses RFM69 - -// #define WITH_LED_RX -// #define WITH_LED_TX - -// #define WITH_GPS_ENABLE // use GPS_ENABLE control line to turn the GPS ON/OFF -// #define WITH_GPS_PPS // use the PPS signal from GPS for precise time-sync. -// #define WITH_GPS_CONFIG // attempt to configure higher GPS baud rate and airborne mode -// #define WITH_GPS_UBX // GPS understands UBX -// #define WITH_GPS_MTK // GPS understands MTK -// #define WITH_GPS_SRF -// #define WITH_MAVLINK - -// #define WITH_GPS_UBX_PASS // to pass directly UBX packets to/from GPS -// #define WITH_GPS_NMEA_PASS // to pass directly NMEA to/from GPS - -// #define WITH_BMP180 // BMP180 pressure sensor -// #define WITH_BMP280 // BMP280 pressure sensor -// #define WITH_BME280 // with humidity -// #define WITH_MS5607 // MS5607 pressure sensor - -// #define WITH_FLARM // Receive FLARM -// #define WITH_PFLAA // PFLAU and PFLAA for compatibility with XCsoar and LK8000 - -// #define WITH_CONFIG // interpret the console input: $POGNS to change parameters - -// #define WITH_BEEPER - -// #define WITH_SD // use the SD card in SPI mode and FAT file system -// #define WITH_SPIFFS // use SPIFFS file system in Flash -// #define WITH_LOG // log own positions and other received to SPIFFS and possibly to uSD - -// #define WITH_BT_SPP // Bluetooth serial port for smartphone/tablet link -// #define WITH_WIFI // attempt to connect to the wifi router for uploading the log files -// #define WITH_SPIFFS_LOG // log transmitted and received packets to SPIFFS - #include "config.h" // user options // ============================================================================================================ +#ifdef WITH_U8G2 +#include "u8g2.h" +#endif + extern uint8_t BARO_I2C; #ifdef WITH_MAVLINK @@ -105,16 +59,32 @@ void GPS_UART_Write (char Byte); // blocking void GPS_UART_SetBaudrate(int BaudRate); bool GPS_PPS_isOn(void); +#ifdef WITH_GPS_ENABLE +void GPS_ENABLE(void); +void GPS_DISABLE(void); +#endif + +// #ifdef WITH_ADSB +int ADSB_UART_Read (uint8_t &Byte); // non-blocking +void ADSB_UART_Write (char Byte); // blocking +void ADSB_UART_SetBaudrate(int BaudRate); +// #endif void RFM_TransferBlock(uint8_t *Data, uint8_t Len); void RFM_RESET(uint8_t On); // RF module reset bool RFM_IRQ_isOn(void); // query the IRQ state #ifdef WITH_OLED +int OLED_DisplayON(uint8_t ON, uint8_t DispIdx=0); // when OFF then low-power mode +int OLED_DisplayINV(uint8_t INV, uint8_t DispIdx=0); int OLED_SetContrast(uint8_t Contrast, uint8_t DispIdx=0); int OLED_PutLine(uint8_t Line, const char *Text, uint8_t DispIdx=0); #endif +#ifdef WITH_U8G2 +extern u8g2_t U8G2_OLED; +#endif + #ifdef WITH_SD esp_err_t SD_Mount(void); void SD_Unmount(); @@ -163,6 +133,9 @@ void LED_RX_Flash(uint8_t Time=100); void LED_TimerCheck(uint8_t Ticks=1); +extern bool Button_SleepRequest; +int32_t Button_TimerCheck(uint8_t Ticks=1); + void IO_Configuration(void); // Configure I/O int NVS_Init(void); // initialize non-volatile-storage in the Flash diff --git a/main/proc.cpp b/main/proc.cpp index c67e89e..d6ce114 100644 --- a/main/proc.cpp +++ b/main/proc.cpp @@ -201,6 +201,10 @@ static void ReadStatus(OGN_Packet &Packet) Format_String(Log_Write, Line, Len); // send the NMEA out to the log file xSemaphoreGive(Log_Mutex); } #endif + +// #ifdef WITH_FollowMe +// Format_String(ADSB_UART_Write, "ADS-B UART test\n"); +// #endif } } diff --git a/main/rf.cpp b/main/rf.cpp index ac8ad5d..6d16f2a 100644 --- a/main/rf.cpp +++ b/main/rf.cpp @@ -207,6 +207,9 @@ extern "C" for( ; ; ) { + while(Button_SleepRequest) + { TRX.WriteMode(RF_OPMODE_SLEEP); + vTaskDelay(100); } uint32_t RxRssiSum=0; uint16_t RxRssiCount=0; // measure the average RSSI for lower frequency do diff --git a/main/sens.cpp b/main/sens.cpp index 570b9c7..f9d9c61 100644 --- a/main/sens.cpp +++ b/main/sens.cpp @@ -315,6 +315,8 @@ void vTaskSENS(void* pvParameters) while(1) { + if(Button_SleepRequest) + { vTaskDelay(1000); } #if defined(WITH_BMP180) || defined(WITH_BMP280) || defined(WITH_MS5607) || defined(WITH_BME280) ProcBaro(); #else