From e6dc55764b9e7cf54d02d59a89089bcd0cb05cc8 Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Fri, 12 May 2023 23:09:00 +0300 Subject: [PATCH] add template for main screen and buttons, need menu etc --- F3:F303/NitrogenFlooding/BMP280.c | 2 +- F3:F303/NitrogenFlooding/buttons.c | 90 ++++++++++++ F3:F303/NitrogenFlooding/buttons.h | 40 +++++ F3:F303/NitrogenFlooding/hardware.c | 4 +- F3:F303/NitrogenFlooding/hardware.h | 16 +- F3:F303/NitrogenFlooding/ili9341.c | 42 ++++-- F3:F303/NitrogenFlooding/ili9341.h | 2 + F3:F303/NitrogenFlooding/incication.h | 32 ++++ F3:F303/NitrogenFlooding/indication.c | 188 ++++++++++++++++++++++++ F3:F303/NitrogenFlooding/main.c | 40 +++-- F3:F303/NitrogenFlooding/nitrogen.bin | Bin 31916 -> 30776 bytes F3:F303/NitrogenFlooding/nitrogen.files | 2 + F3:F303/NitrogenFlooding/proto.c | 44 ++++-- F3:F303/NitrogenFlooding/screen.c | 3 +- F3:F303/NitrogenFlooding/screen.h | 46 ++++++ F3:F303/NitrogenFlooding/version.inc | 4 +- makefile.stm32 | 2 +- 17 files changed, 500 insertions(+), 57 deletions(-) create mode 100644 F3:F303/NitrogenFlooding/buttons.c create mode 100644 F3:F303/NitrogenFlooding/buttons.h create mode 100644 F3:F303/NitrogenFlooding/incication.h create mode 100644 F3:F303/NitrogenFlooding/indication.c diff --git a/F3:F303/NitrogenFlooding/BMP280.c b/F3:F303/NitrogenFlooding/BMP280.c index 4770a2b..7cf963d 100644 --- a/F3:F303/NitrogenFlooding/BMP280.c +++ b/F3:F303/NitrogenFlooding/BMP280.c @@ -359,6 +359,6 @@ int BMP280_getdata(float *T, float *P, float *H){ // dewpoint calculation (T in degrC, H in percents) float Tdew(float T, float H){ - float gamma = 17.27f * T / (237.7f + T) + log(H/100.f); + float gamma = 17.27f * T / (237.7f + T) + logf(H/100.f); return (237.7f * gamma)/(17.27 - gamma); } diff --git a/F3:F303/NitrogenFlooding/buttons.c b/F3:F303/NitrogenFlooding/buttons.c new file mode 100644 index 0000000..a1a0231 --- /dev/null +++ b/F3:F303/NitrogenFlooding/buttons.c @@ -0,0 +1,90 @@ +/* + * This file is part of the nitrogen project. + * Copyright 2023 Edward V. Emelianov . + * + * 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 . + */ + +#include "buttons.h" +#include "hardware.h" + +typedef struct{ + keyevent event; // current key event + int16_t counter; // press/release counter + uint32_t lastTms; // time of last event change +} keybase; + +static keybase allkeys[BTNSNO] = {0}; // array for buttons' states + +uint32_t lastUnsleep = 0; // last keys activity time + +void process_keys(){ + static uint32_t lastT = 0; + if(Tms == lastT) return; + uint16_t d = (uint16_t)(Tms - lastT); + lastT = Tms; + for(int i = 0; i < BTNSNO; ++i){ + keybase *k = &allkeys[i]; + keyevent e = k->event; + if(BTN_state(i)){ // key is in pressed state + switch(e){ + case EVT_NONE: // just pressed + case EVT_RELEASE: + if((k->counter += d) > PRESSTHRESHOLD){ + k->event = EVT_PRESS; + } + break; + case EVT_PRESS: // hold + if((k->counter += d)> HOLDTHRESHOLD){ + k->event = EVT_HOLD; + } + break; + default: + break; + } + }else{ // released + if(e == EVT_PRESS || e == EVT_HOLD){ // released + if(k->counter > PRESSTHRESHOLD) k->counter = PRESSTHRESHOLD; + else if((k->counter -= d) < 0){ + k->event = EVT_RELEASE; // button released + } + } + } + if(e != k->event){ + k->lastTms = Tms; + lastUnsleep = Tms; + } + } +} + +/** + * @brief keystate - curent key state + * @param k - key number + * @param T - last event changing time + * @return key event + */ +keyevent keystate(uint8_t k, uint32_t *T){ + if(k >= BTNSNO) return EVT_NONE; + keyevent evt = allkeys[k].event; + // change state `release` to `none` after 1st check + if(evt == EVT_RELEASE) allkeys[k].event = EVT_NONE; + if(T) *T = allkeys[k].lastTms; + return evt; +} + +// getter of keyevent for allkeys[] +keyevent keyevt(uint8_t k){ + if(k >= BTNSNO) return EVT_NONE; + return allkeys[k].event; +} diff --git a/F3:F303/NitrogenFlooding/buttons.h b/F3:F303/NitrogenFlooding/buttons.h new file mode 100644 index 0000000..f981e30 --- /dev/null +++ b/F3:F303/NitrogenFlooding/buttons.h @@ -0,0 +1,40 @@ +/* + * This file is part of the nitrogen project. + * Copyright 2023 Edward V. Emelianov . + * + * 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 . + */ + +#pragma once + +#include + +// threshold in ms for press/hold +#define PRESSTHRESHOLD (9) +#define HOLDTHRESHOLD (199) + +// events +typedef enum{ + EVT_NONE, // no events with given key + EVT_PRESS, // pressed (hold more than PRESSTHRESHOLD ms) + EVT_HOLD, // hold more than HOLDTHRESHOLD ms + EVT_RELEASE // released after press or hold state +} keyevent; + +extern uint32_t lastUnsleep; // last keys activity time + +void process_keys(); +keyevent keystate(uint8_t k, uint32_t *T); +keyevent keyevt(uint8_t k); + diff --git a/F3:F303/NitrogenFlooding/hardware.c b/F3:F303/NitrogenFlooding/hardware.c index e31aefa..1ba7ef6 100644 --- a/F3:F303/NitrogenFlooding/hardware.c +++ b/F3:F303/NitrogenFlooding/hardware.c @@ -20,7 +20,7 @@ #include "i2c.h" #include "spi.h" -int LEDsON = 1; +int LEDsON = 0; // setup here ALL GPIO pins (due to table in Readme.md) // leave SWD as default AF; high speed for CLK and some other AF; med speed for some another AF @@ -161,7 +161,7 @@ void setPWM(int nch, uint16_t val){ } } -uint8_t getPWM(int nch){ +uint16_t getPWM(int nch){ switch(nch){ case 0: return TIM3->CCR1; diff --git a/F3:F303/NitrogenFlooding/hardware.h b/F3:F303/NitrogenFlooding/hardware.h index bfbbaa2..fe872fc 100644 --- a/F3:F303/NitrogenFlooding/hardware.h +++ b/F3:F303/NitrogenFlooding/hardware.h @@ -48,16 +48,18 @@ #define LED_off(x) do{pin_set(LEDs_port, 1<<(8+x));}while(0) #define LED_on(x) do{if(LEDsON) pin_clear(LEDs_port, 1<<(8+x));}while(0) #define LED_get(x) (LEDs_port->IDR & 1<<(8+x) ? 0 : 1) +#define LEDS_OFF() do{LEDsON = 0; for(int _ = 0; _ < 4; ++_) LED_off(_);}while(0) +#define LEDS_ON() do{LEDsON = 1;}while(0) // screen LEDon/off - PB12; reset - PB11; data/command - PB10 #define SCRN_LED_pin (1<<12) #define SCRN_LED_port (GPIOB) #define SCRN_LED_set(a) do{if(a) pin_set(SCRN_LED_port, SCRN_LED_pin); else pin_clear(SCRN_LED_port, SCRN_LED_pin);}while(0) #define SCRN_LED_get() (SCRN_LED_port->IDR & SCRN_LED_pin ? 1: 0) -#define SCRN_RST_pin (1<<11) -#define SCRN_RST_port (GPIOB) -#define SCRN_RST_set(a) do{if(a) pin_set(SCRN_RST_port, SCRN_RST_pin); else pin_clear(SCRN_RST_port, SCRN_RST_pin);}while(0) -#define SCRN_RST_get() (SCRN_RST_port->IDR & SCRN_RST_pin ? 1: 0) +#define SCRN_CS_pin (1<<11) +#define SCRN_CS_port (GPIOB) +#define SCRN_CS_set(a) do{if(a) pin_set(SCRN_CS_port, SCRN_CS_pin); else pin_clear(SCRN_CS_port, SCRN_CS_pin);}while(0) +#define SCRN_CS_get() (SCRN_CS_port->IDR & SCRN_CS_pin ? 1: 0) #define SCRN_DCX_pin (1<<10) #define SCRN_DCX_port (GPIOB) #define SCRN_DCX_get() (SCRN_DCX_port->IDR & SCRN_DCX_pin ? 1: 0) @@ -77,6 +79,10 @@ #define BTN6_pin (1<<15) // state 0 - pressed, 1 - released #define BTN_state(x) (BTNs_port->IDR & 1<<(9+x) ? 0 : 1) +// timeout to turn off screen and LEDs after no keys activity - 300 seconds +#define BTN_ACTIVITY_TIMEOUT (300000) +// refresh interval for BME280 and other data - 2.5s +#define SENSORS_DATA_TIMEOUT (2500) // buzzer, ADC voltage #define BUZZER_port GPIOB @@ -96,4 +102,4 @@ uint8_t MSB(uint16_t val); void hw_setup(); void setPWM(int nch, uint16_t val); -uint8_t getPWM(int nch); +uint16_t getPWM(int nch); diff --git a/F3:F303/NitrogenFlooding/ili9341.c b/F3:F303/NitrogenFlooding/ili9341.c index beaac7a..8e92f4d 100644 --- a/F3:F303/NitrogenFlooding/ili9341.c +++ b/F3:F303/NitrogenFlooding/ili9341.c @@ -79,6 +79,22 @@ int ili9341_init(){ return 1; } +// turn screen ON of OFF +int ili9341_on(){ + SCRN_LED_set(1); + if(!ili9341_writecmd(ILI9341_SLPOUT)) return 0; + if(!ili9341_writecmd(ILI9341_NORON)) return 0; + if(!ili9341_writecmd(ILI9341_DISPON)) return 0; + return 1; +} + +int ili9341_off(){ + SCRN_LED_set(0); + if(!ili9341_writecmd(ILI9341_SLPIN)) return 0; + if(!ili9341_writecmd(ILI9341_DISPOFF)) return 0; + return 1; +} + /** * @brief il9341_readreg - read data from register * @param reg - register @@ -88,7 +104,7 @@ int ili9341_init(){ */ int ili9341_readreg(uint8_t reg, uint8_t *data, uint32_t N){ SCRN_Command(); - SCRN_RST_set(0); + SCRN_CS_set(0); int r = 0; do{ if(!spi_write(®, 1)) break; @@ -99,7 +115,7 @@ int ili9341_readreg(uint8_t reg, uint8_t *data, uint32_t N){ r = 1; }while(0); SCRN_Command(); - SCRN_RST_set(1); + SCRN_CS_set(1); return r; } @@ -112,7 +128,7 @@ int ili9341_readreg(uint8_t reg, uint8_t *data, uint32_t N){ */ int ili9341_writereg(uint8_t reg, const uint8_t *data, uint32_t N){ SCRN_Command(); - SCRN_RST_set(0); + SCRN_CS_set(0); int r = 0; do{ if(!spi_write(®, 1)) break; @@ -123,14 +139,14 @@ int ili9341_writereg(uint8_t reg, const uint8_t *data, uint32_t N){ r = 1; }while(0); SCRN_Command(); - SCRN_RST_set(1); + SCRN_CS_set(1); return r; } // write register with uint16_t data (swap bytes) int ili9341_writereg16(uint8_t reg, const uint16_t data){ SCRN_Command(); - SCRN_RST_set(0); + SCRN_CS_set(0); int r = 0; do{ if(!spi_write(®, 1)) break; @@ -142,13 +158,13 @@ int ili9341_writereg16(uint8_t reg, const uint16_t data){ r = 1; }while(0); SCRN_Command(); - SCRN_RST_set(1); + SCRN_CS_set(1); return r; } int ili9341_writereg32(uint8_t reg, uint16_t data1, uint16_t data2){ SCRN_Command(); - SCRN_RST_set(0); + SCRN_CS_set(0); int r = 0; do{ if(!spi_write(®, 1)) break; @@ -162,21 +178,21 @@ int ili9341_writereg32(uint8_t reg, uint16_t data1, uint16_t data2){ r = 1; }while(0); SCRN_Command(); - SCRN_RST_set(1); + SCRN_CS_set(1); return r; } // write simple command int ili9341_writecmd(uint8_t cmd){ SCRN_Command(); - SCRN_RST_set(0); + SCRN_CS_set(0); int r = 0; do{ if(!spi_write(&cmd, 1)) break; if(!spi_waitbsy()) break; r = 1; }while(0); - SCRN_RST_set(1); + SCRN_CS_set(1); return r; } @@ -185,7 +201,7 @@ static int dmardwr(uint8_t *out, uint8_t *in, uint32_t N){ if(!out || !N) return 0; if(in) bzero(out, N); SCRN_Data(); - SCRN_RST_set(0); + SCRN_CS_set(0); uint32_t r = 0; do{ if(!spi_write_dma((const uint8_t*)out, in, N)) break; @@ -197,7 +213,7 @@ static int dmardwr(uint8_t *out, uint8_t *in, uint32_t N){ else r = 1; }while(0); SCRN_Command(); - SCRN_RST_set(1); + SCRN_CS_set(1); return r; } @@ -214,7 +230,7 @@ int ili9341_readdata(uint8_t *data, uint32_t N){ int ili9341_readregdma(uint8_t reg, uint8_t *data, uint32_t N){ SCRN_Command(); - SCRN_RST_set(0); + SCRN_CS_set(0); int r = 0; do{ if(!spi_write(®, 1)) break; diff --git a/F3:F303/NitrogenFlooding/ili9341.h b/F3:F303/NitrogenFlooding/ili9341.h index ae5627e..853001d 100644 --- a/F3:F303/NitrogenFlooding/ili9341.h +++ b/F3:F303/NitrogenFlooding/ili9341.h @@ -173,6 +173,8 @@ extern uint16_t colorbuf[]; int ili9341_init(); +int ili9341_on(); +int ili9341_off(); int ili9341_readreg(uint8_t reg, uint8_t *data, uint32_t N); int ili9341_writereg(uint8_t reg, const uint8_t *data, uint32_t N); int ili9341_writereg16(uint8_t reg, uint16_t data); diff --git a/F3:F303/NitrogenFlooding/incication.h b/F3:F303/NitrogenFlooding/incication.h new file mode 100644 index 0000000..afbf7a2 --- /dev/null +++ b/F3:F303/NitrogenFlooding/incication.h @@ -0,0 +1,32 @@ +/* + * This file is part of the nitrogen project. + * Copyright 2023 Edward V. Emelianov . + * + * 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 . + */ + +#pragma once + +// temporary defines - should be stored in settings +// temperature (degC) limits +#define T_MIN (-20.f) +#define T_MAX (40.f) +// pressure (Pa) limit +#define P_MAX (120e3f) +// humidity limit +#define H_MAX (90.f) +// minimal difference above dew point +#define DEW_MIN (3.f) + +void indication_process(); diff --git a/F3:F303/NitrogenFlooding/indication.c b/F3:F303/NitrogenFlooding/indication.c new file mode 100644 index 0000000..e6bacf0 --- /dev/null +++ b/F3:F303/NitrogenFlooding/indication.c @@ -0,0 +1,188 @@ +/* + * This file is part of the nitrogen project. + * Copyright 2023 Edward V. Emelianov . + * + * 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 . + */ + +#include "BMP280.h" +#include "buttons.h" +#include "hardware.h" +#include "ili9341.h" +#include "incication.h" +#include "screen.h" +#include "strfunc.h" +#include "usb.h" + +/* + * LEDs: + * 0 - blinks all the time + * 1 - PWM2 state (blinks as longer as PWM larger) + * 2 - PWM3 state (-//-) + * 3 - ? + */ +// next state change time +static uint32_t ledT[LEDS_AMOUNT] = {0}; +// arrays of high and low states' length +static uint32_t ledH[LEDS_AMOUNT] = {199, 0, 0, 0}; +static uint32_t ledL[LEDS_AMOUNT] = {799, 1, 1, 1}; + +// led blinking +TRUE_INLINE void leds_proc(){ + uint32_t v = getPWM(2); + ledH[1] = v*5; ledL[1] = (PWM_CCR_MAX - v) * 5; + v = getPWM(3); + ledH[2] = v*5; ledL[2] = (PWM_CCR_MAX - v) * 5; + for(int i = 0; i < LEDS_AMOUNT; ++i){ + int state = LED_get(i); + if(state){ // shining + if(ledH[i] == 0) LED_off(i); // don't turn it on + else if(ledL[i] && Tms > ledT[i]){ + LED_off(i); + ledT[i] = Tms + ledL[i]; + } + }else{ + if(ledL[i] == 0) LED_on(i); // don't turn it off + else if(ledH[i] && Tms > ledT[i]){ + LED_on(i); + ledT[i] = Tms + ledH[i]; + } + } + } +} + +// Display state: main window or menu +typedef enum{ + DISP_MAINWIN, + DISP_MENU +} display_state; + +static display_state dispstate = DISP_MAINWIN; +static uint32_t lastTmeas = 0; // last measurement time + +static void cls(){ // set default colors (bg=0, fg=0xffff) and clear screen + setBGcolor(0); + setFGcolor(0xffff); + ClearScreen(); +} + +static void refresh_mainwin(){ // ask all parameters and refresh main window with new values + DBG("REFRESH main window"); + cls(); + float T, P, H; + BMP280_status s = BMP280_get_status(); + if(s == BMP280_NOTINIT || s == BMP280_ERR) BMP280_init(); + SetFontScale(1); // small menu items labels + setBGcolor(COLOR_BLACK); setFGcolor(COLOR_LIGHTGREEN); + PutStringAt(4, 16, "Temperature Pressure Humidity Dew point"); + int y = 37; + uint16_t fgcolor; + if(s == BMP280_RDY && BMP280_getdata(&T, &P, &H)){ // show data + if(T < T_MIN || T > T_MAX) fgcolor = COLOR_RED; + else if(T < 0) fgcolor = COLOR_BLUE; + else fgcolor = COLOR_GREEN; + setFGcolor(fgcolor); PutStringAt(32, y, float2str(T, 2)); + if(P > P_MAX) fgcolor = COLOR_RED; + else fgcolor = COLOR_YELLOW; + setFGcolor(fgcolor); PutStringAt(112, y, float2str(P, 1)); + if(H > H_MAX) fgcolor = COLOR_RED; + else fgcolor = COLOR_CHOCOLATE; + setFGcolor(fgcolor); PutStringAt(192, y, float2str(H, 1)); + float dew = Tdew(T, H); + if(T - dew < DEW_MIN) fgcolor = COLOR_RED; + else fgcolor = COLOR_LIGHTBLUE; + setFGcolor(fgcolor); PutStringAt(248, y, float2str(dew, 1)); +#ifdef EBUG + USB_sendstr("T="); USB_sendstr(float2str(T, 2)); USB_sendstr("\nP="); + USB_sendstr(float2str(P, 1)); + P *= 0.00750062f; USB_sendstr("\nPmm="); USB_sendstr(float2str(P, 1)); + USB_sendstr("\nH="); USB_sendstr(float2str(H, 1)); + USB_sendstr("\nTdew="); USB_sendstr(float2str(dew, 1)); + newline(); +#endif + }else{ // show "errr" + setBGcolor(COLOR_RED); setFGcolor(COLOR_CYAN); + CenterStringAt(y, "No signal"); + } + // display all other data + SetFontScale(3); + // TODO: show current level + setFGcolor(COLOR_RED); CenterStringAt(130, "Level: NULL"); + if(getPWM(2) || getPWM(3)){ + setFGcolor(COLOR_GREEN); + CenterStringAt(220, "Processing"); + } + UpdateScreen(0, SCRNH-1); + if(!BMP280_start()) BMP280_init(); // start new measurement +} + +static void refresh_menu(){ // refresh menu with changed selection + DBG("REFRESH menu"); + cls(); +} + +/* + * Custom keys: + * 0 - main screen + * 1 - up + * 2 - down + * 3 - select/menu + */ +TRUE_INLINE void btns_proc(){ + uint8_t evtmask = 0; // bitmask for active buttons (==1) + for(int i = 0; i < BTNSNO; ++i){ + keyevent evt = keystate(i, NULL); // T may be used for doubleclick detection + if(evt == EVT_PRESS || evt == EVT_HOLD) evtmask |= 1< SENSORS_DATA_TIMEOUT){ + refresh_mainwin(); + lastTmeas = Tms; + } + break; + case DISP_MENU: // do nothing + ; + break; + } +} diff --git a/F3:F303/NitrogenFlooding/main.c b/F3:F303/NitrogenFlooding/main.c index 39b5504..0dd74f7 100644 --- a/F3:F303/NitrogenFlooding/main.c +++ b/F3:F303/NitrogenFlooding/main.c @@ -18,11 +18,13 @@ #include "adc.h" #include "BMP280.h" -//#include "buttons.h" +#include "buttons.h" //#include "can.h" //#include "flash.h" #include "hardware.h" #include "i2c.h" +#include "ili9341.h" +#include "incication.h" #include "proto.h" #include "screen.h" #include "strfunc.h" @@ -54,14 +56,9 @@ int main(void){ adc_setup(); BMP280_setup(0); USBPU_ON(); - uint32_t ctr = 0; // CAN_message *can_mesg; while(1){ IWDG->KR = IWDG_REFRESH; - if(Tms - ctr > 499){ - ctr = Tms; - LED_blink(0); - } /*CAN_proc(); if(CAN_get_status() == CAN_FIFO_OVERRUN){ USB_sendstr("CAN bus fifo overrun occured!\n"); @@ -94,21 +91,6 @@ int main(void){ } //i2c_have_DMA_Rx(); // check if there's DMA Rx complete BMP280_process(); - BMP280_status s = BMP280_get_status(); - if(s == BMP280_RDY){ // data ready - get it - float T, P, H; - if(BMP280_getdata(&T, &P, &H)){ - USB_sendstr("T="); USB_sendstr(float2str(T, 2)); USB_sendstr("\nP="); - USB_sendstr(float2str(P, 1)); - P *= 0.00750062f; USB_sendstr("\nPmm="); USB_sendstr(float2str(P, 1)); - USB_sendstr("\nH="); USB_sendstr(float2str(H, 1)); - USB_sendstr("\nTdew="); USB_sendstr(float2str(Tdew(T, H), 1)); - newline(); - }else USB_sendstr("Can't read data\n"); - }else if(s == BMP280_ERR){ - USB_sendstr("BME280 error\n"); - BMP280_init(); - } int l = USB_receivestr(inbuff, MAXSTRLEN); if(l < 0) USB_sendstr("ERROR: USB buffer overflow or string was too long\n"); else if(l){ @@ -116,6 +98,20 @@ int main(void){ if(ans) USB_sendstr(ans); } process_screen(); - //process_keys(); + process_keys(); + // turn off screen and LEDs if no keys was pressed last X ms + if(LEDsON){ + if(Tms - lastUnsleep > BTN_ACTIVITY_TIMEOUT){ // timeout - turn off LEDs and screen + LEDS_OFF(); + ili9341_off(); + }else{ // check operation buttons for menu etc + indication_process(); + } + }else{ + if(Tms - lastUnsleep < BTN_ACTIVITY_TIMEOUT/2){ // recent activity - turn on indication + LEDS_ON(); + ili9341_on(); + } + } } } diff --git a/F3:F303/NitrogenFlooding/nitrogen.bin b/F3:F303/NitrogenFlooding/nitrogen.bin index 805c2d59f99a22e65ea5dffeb61c3f7202257223..61c4c13bce9f9d41017c06c5217029cae4e3f3ce 100755 GIT binary patch delta 10014 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 delta 11093 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 255) return RET_WRONGPARNO; if(c){ @@ -271,7 +272,13 @@ static int scrninit(const char _U_ *cmd, int _U_ parno, const char _U_ *c, int32 USB_sendstr(OK); return RET_GOOD; } - +static int scrnonoff(const char _U_ *cmd, int _U_ parno, const char *c, int32_t i){ + if(!c) return RET_WRONGARG; + int r = (i) ? ili9341_on() : ili9341_off(); + if(!r) return RET_BAD; + sendkeyu(cmd, -1, i); + return RET_GOOD; +} static int scrnfill(const char *cmd, int parno, const char *c, int32_t i){ if(parno < 0) parno = RGB(0xf, 0x1f, 0xf); if(parno > 0xffff) return RET_WRONGPARNO; @@ -332,6 +339,12 @@ static int scls(const char *cmd, int parno, const char *c, int32_t i){ sendkeyuhex(cmd, parno, i); return RET_GOOD; } +static int srefr(const char _U_ *cmd, int _U_ parno, const char _U_ *c, int32_t _U_ i){ + UpdateScreen(0, SCRNH-1); + USB_sendstr(OK); + return RET_GOOD; +} + static int scolor(const char *cmd, int parno, const char *c, int32_t i){ // fg=bg, default: fg=0xffff, bg=0 if(parno < 0 || parno > 0xffff) parno = 0xffff; @@ -381,6 +394,16 @@ static int sfscale(const char *cmd, int _U_ parno, const char _U_ *c, int32_t i) return RET_GOOD; } +static int buttons(const char *cmd, int parno, const char _U_ *c, int32_t _U_ i){ + if(parno < 0 || parno >= BTNSNO) return RET_WRONGPARNO; + uint32_t T; + keyevent evt = keystate((uint8_t)parno, &T); + sendkeyu(cmd, parno, evt); + if(evt != EVT_NONE){ + USB_sendstr("Tevent="); USB_sendstr(u2str(T)); newline(); + } + return RET_GOOD; +} typedef struct{ int (*fn)(const char*, int, const char*, int32_t); @@ -393,8 +416,9 @@ commands cmdlist[] = { {NULL, "Different commands", NULL}, {bme, "BME", "get pressure, temperature and humidity"}, {bmefilter, "BMEf", "set filter (0..4)"}, + {buttons, "button", "get buttonx state"}, {buzzer, "buzzer", "get/set (0 - off, 1 - on) buzzer"}, - {leds, "LED", "LEDx=y; where x=0..3 to work with single LED (then y=1-set, 0-reset, 2-toggle), absent to work with all (y=0 - disable, 1-enable)"}, + {leds, "LED", "LEDx=y; where x=0..3 to work with single LED (then y=1-set, 0-reset, 2-toggle), absent to set LEDsON (y=0 - disable, 1-enable)"}, {pwm, "pwm", "set/get x channel (0..3) pwm value (0..100)"}, {reset, "reset", "reset MCU"}, {tms, "tms", "print Tms"}, @@ -406,7 +430,7 @@ commands cmdlist[] = { {NULL, "Screen commands", NULL}, {scrnled, "Sled", "turn on/off screen lights"}, {scrndcr, "Sdcr", "set data(1)/command(0)"}, - {scrnrst, "Srst", "reset (1/0)"}, + // {scrnrst, "Srst", "reset (1/0)"}, {scrnrdwr, "Sreg", "read/write 8-bit register"}, {scrnrdwr4, "Sregx", "read/write 32-bit register"}, {scrnrdn, "Sregn", "read from register x =n bytes"}, @@ -415,12 +439,14 @@ commands cmdlist[] = { {scrndata4, "Sdatn", "write x bytes of =data"}, {sread, "Sread", "read "}, {scrninit, "Sini", "init screen"}, + {scrnonoff, "Spower", "=0 - off, =1 - on"}, {scrnfill, "Sfill", "fill screen with color (=npix)"}, {scrnfilln, "Sfilln", "fill screen (next) with color (=npix)"}, {smadctl, "Smad", "change MADCTL"}, {scol, "Scol", "set column limits (low=high)"}, {srow, "Srow", "set row limits (low=high)"}, {scls, "Scls", "clear screen fg=bg"}, + {srefr, "Srefresh", "refresh full screen"}, {scolor, "Scolor", "seg color fg=bg"}, {sputstr, "Sstr", "put string y=string"}, {sstate, "Sstate", "current screen state"}, diff --git a/F3:F303/NitrogenFlooding/screen.c b/F3:F303/NitrogenFlooding/screen.c index c1ff253..63dcb40 100644 --- a/F3:F303/NitrogenFlooding/screen.c +++ b/F3:F303/NitrogenFlooding/screen.c @@ -90,7 +90,6 @@ void ClearScreen(){ foreground[i] = fgColor; background[i] = bgColor; } - for(int i = SPRITE_SZ-40; i < SPRITE_SZ; ++i) foreground[i] = i; UpdateScreen(0, SCRNH-1); } @@ -199,7 +198,7 @@ int strpixlen(const char *str){ const uint8_t *c = font_char(*str++); if(c) l += *c; } - return l; + return l * fontscale; } // convert buffer to update (return 0 if all sent) diff --git a/F3:F303/NitrogenFlooding/screen.h b/F3:F303/NitrogenFlooding/screen.h index a912f7f..fd2e567 100644 --- a/F3:F303/NitrogenFlooding/screen.h +++ b/F3:F303/NitrogenFlooding/screen.h @@ -42,6 +42,52 @@ typedef enum{ // screen states // maximal font scale #define FONTSCALEMAX (10) +// some base colors +#define COLOR_BLACK 0x0000 +#define COLOR_BLUE 0x001F +#define COLOR_BROWN 0xA145 +#define COLOR_CHOCOLATE 0xD343 +#define COLOR_CYAN 0x07FF +#define COLOR_DARKBLUE 0x0011 +#define COLOR_DARKCYAN 0x03EF +#define COLOR_DARKGRAY 0x8410 +#define COLOR_DARKGREEN 0x03E0 +#define COLOR_DARKMAGENTA 0x8811 +#define COLOR_DARKORANGE 0xFC60 +#define COLOR_DARKRED 0x8800 +#define COLOR_DARKVIOLET 0x901A +#define COLOR_DEEPPINK 0xF8B2 +#define COLOR_GOLD 0xFEA0 +#define COLOR_GRAY 0xAD55 +#define COLOR_GREEN 0x07E0 +#define COLOR_GREENYELLOW 0xAFE5 +#define COLOR_INDIGO 0x4810 +#define COLOR_KHAKI 0xF731 +#define COLOR_LIGHTBLUE 0xAEDC +#define COLOR_LIGHTCYAN 0xE7FF +#define COLOR_LIGHTGREEN 0x9772 +#define COLOR_LIGHTGRAY 0xC618 +#define COLOR_LIGHTYELLOW 0xFFFC +#define COLOR_MAGENTA 0xF81F +#define COLOR_MEDIUMBLUE 0x0019 +#define COLOR_NAVY 0x000F +#define COLOR_OLIVE 0x7BE0 +#define COLOR_ORANGE 0xFD20 +#define COLOR_ORANGERED 0xFA20 +#define COLOR_PALEGREEN 0x9FD3 +#define COLOR_PINK 0xF81F +#define COLOR_PURPLE 0x780F +#define COLOR_RED 0xf800 +#define COLOR_SEAGREEN 0x2C4A +#define COLOR_SKYBLUE 0x867D +#define COLOR_SPRINGGREEN 0x07EF +#define COLOR_STEELBLUE 0x4416 +#define COLOR_TOMATO 0xFB08 +#define COLOR_WHITE 0xFFFF +#define COLOR_YELLOW 0xFFE0 +#define COLOR_YELLOWGREEN 0x9E66 + + screen_state getScreenState(); void ClearScreen(); void UpdateScreen(int y0, int y1); diff --git a/F3:F303/NitrogenFlooding/version.inc b/F3:F303/NitrogenFlooding/version.inc index 3a1d7b1..f64e00a 100644 --- a/F3:F303/NitrogenFlooding/version.inc +++ b/F3:F303/NitrogenFlooding/version.inc @@ -1,2 +1,2 @@ -#define BUILD_NUMBER "242" -#define BUILD_DATE "2023-05-11" +#define BUILD_NUMBER "253" +#define BUILD_DATE "2023-05-12" diff --git a/makefile.stm32 b/makefile.stm32 index 6e51ee4..6fb8ab5 100644 --- a/makefile.stm32 +++ b/makefile.stm32 @@ -48,7 +48,7 @@ LIB_DIR := $(INC_DIR)/ld ############################################################################### # C flags CFLAGS += -O2 -D__thumb2__=1 -MD -CFLAGS += -Wall -Wextra -Wshadow +CFLAGS += -Wall -Wextra -Wshadow -Wdouble-promotion CFLAGS += -fshort-enums -ffunction-sections -fdata-sections #CFLAGS += -fno-common -fno-stack-protector CFLAGS += $(ARCH_FLAGS)