add template for main screen and buttons, need menu etc

This commit is contained in:
Edward Emelianov 2023-05-12 23:09:00 +03:00
parent e63b29435c
commit e6dc55764b
17 changed files with 500 additions and 57 deletions

View File

@ -359,6 +359,6 @@ int BMP280_getdata(float *T, float *P, float *H){
// dewpoint calculation (T in degrC, H in percents) // dewpoint calculation (T in degrC, H in percents)
float Tdew(float T, float H){ 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); return (237.7f * gamma)/(17.27 - gamma);
} }

View File

@ -0,0 +1,90 @@
/*
* This file is part of the nitrogen project.
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#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;
}

View File

@ -0,0 +1,40 @@
/*
* This file is part of the nitrogen project.
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stm32f3.h>
// 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);

View File

@ -20,7 +20,7 @@
#include "i2c.h" #include "i2c.h"
#include "spi.h" #include "spi.h"
int LEDsON = 1; int LEDsON = 0;
// setup here ALL GPIO pins (due to table in Readme.md) // 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 // 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){ switch(nch){
case 0: case 0:
return TIM3->CCR1; return TIM3->CCR1;

View File

@ -48,16 +48,18 @@
#define LED_off(x) do{pin_set(LEDs_port, 1<<(8+x));}while(0) #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_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 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 // screen LEDon/off - PB12; reset - PB11; data/command - PB10
#define SCRN_LED_pin (1<<12) #define SCRN_LED_pin (1<<12)
#define SCRN_LED_port (GPIOB) #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_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_LED_get() (SCRN_LED_port->IDR & SCRN_LED_pin ? 1: 0)
#define SCRN_RST_pin (1<<11) #define SCRN_CS_pin (1<<11)
#define SCRN_RST_port (GPIOB) #define SCRN_CS_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_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_RST_get() (SCRN_RST_port->IDR & SCRN_RST_pin ? 1: 0) #define SCRN_CS_get() (SCRN_CS_port->IDR & SCRN_CS_pin ? 1: 0)
#define SCRN_DCX_pin (1<<10) #define SCRN_DCX_pin (1<<10)
#define SCRN_DCX_port (GPIOB) #define SCRN_DCX_port (GPIOB)
#define SCRN_DCX_get() (SCRN_DCX_port->IDR & SCRN_DCX_pin ? 1: 0) #define SCRN_DCX_get() (SCRN_DCX_port->IDR & SCRN_DCX_pin ? 1: 0)
@ -77,6 +79,10 @@
#define BTN6_pin (1<<15) #define BTN6_pin (1<<15)
// state 0 - pressed, 1 - released // state 0 - pressed, 1 - released
#define BTN_state(x) (BTNs_port->IDR & 1<<(9+x) ? 0 : 1) #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 // buzzer, ADC voltage
#define BUZZER_port GPIOB #define BUZZER_port GPIOB
@ -96,4 +102,4 @@ uint8_t MSB(uint16_t val);
void hw_setup(); void hw_setup();
void setPWM(int nch, uint16_t val); void setPWM(int nch, uint16_t val);
uint8_t getPWM(int nch); uint16_t getPWM(int nch);

View File

@ -79,6 +79,22 @@ int ili9341_init(){
return 1; 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 * @brief il9341_readreg - read data from register
* @param reg - register * @param reg - register
@ -88,7 +104,7 @@ int ili9341_init(){
*/ */
int ili9341_readreg(uint8_t reg, uint8_t *data, uint32_t N){ int ili9341_readreg(uint8_t reg, uint8_t *data, uint32_t N){
SCRN_Command(); SCRN_Command();
SCRN_RST_set(0); SCRN_CS_set(0);
int r = 0; int r = 0;
do{ do{
if(!spi_write(&reg, 1)) break; if(!spi_write(&reg, 1)) break;
@ -99,7 +115,7 @@ int ili9341_readreg(uint8_t reg, uint8_t *data, uint32_t N){
r = 1; r = 1;
}while(0); }while(0);
SCRN_Command(); SCRN_Command();
SCRN_RST_set(1); SCRN_CS_set(1);
return r; 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){ int ili9341_writereg(uint8_t reg, const uint8_t *data, uint32_t N){
SCRN_Command(); SCRN_Command();
SCRN_RST_set(0); SCRN_CS_set(0);
int r = 0; int r = 0;
do{ do{
if(!spi_write(&reg, 1)) break; if(!spi_write(&reg, 1)) break;
@ -123,14 +139,14 @@ int ili9341_writereg(uint8_t reg, const uint8_t *data, uint32_t N){
r = 1; r = 1;
}while(0); }while(0);
SCRN_Command(); SCRN_Command();
SCRN_RST_set(1); SCRN_CS_set(1);
return r; return r;
} }
// write register with uint16_t data (swap bytes) // write register with uint16_t data (swap bytes)
int ili9341_writereg16(uint8_t reg, const uint16_t data){ int ili9341_writereg16(uint8_t reg, const uint16_t data){
SCRN_Command(); SCRN_Command();
SCRN_RST_set(0); SCRN_CS_set(0);
int r = 0; int r = 0;
do{ do{
if(!spi_write(&reg, 1)) break; if(!spi_write(&reg, 1)) break;
@ -142,13 +158,13 @@ int ili9341_writereg16(uint8_t reg, const uint16_t data){
r = 1; r = 1;
}while(0); }while(0);
SCRN_Command(); SCRN_Command();
SCRN_RST_set(1); SCRN_CS_set(1);
return r; return r;
} }
int ili9341_writereg32(uint8_t reg, uint16_t data1, uint16_t data2){ int ili9341_writereg32(uint8_t reg, uint16_t data1, uint16_t data2){
SCRN_Command(); SCRN_Command();
SCRN_RST_set(0); SCRN_CS_set(0);
int r = 0; int r = 0;
do{ do{
if(!spi_write(&reg, 1)) break; if(!spi_write(&reg, 1)) break;
@ -162,21 +178,21 @@ int ili9341_writereg32(uint8_t reg, uint16_t data1, uint16_t data2){
r = 1; r = 1;
}while(0); }while(0);
SCRN_Command(); SCRN_Command();
SCRN_RST_set(1); SCRN_CS_set(1);
return r; return r;
} }
// write simple command // write simple command
int ili9341_writecmd(uint8_t cmd){ int ili9341_writecmd(uint8_t cmd){
SCRN_Command(); SCRN_Command();
SCRN_RST_set(0); SCRN_CS_set(0);
int r = 0; int r = 0;
do{ do{
if(!spi_write(&cmd, 1)) break; if(!spi_write(&cmd, 1)) break;
if(!spi_waitbsy()) break; if(!spi_waitbsy()) break;
r = 1; r = 1;
}while(0); }while(0);
SCRN_RST_set(1); SCRN_CS_set(1);
return r; return r;
} }
@ -185,7 +201,7 @@ static int dmardwr(uint8_t *out, uint8_t *in, uint32_t N){
if(!out || !N) return 0; if(!out || !N) return 0;
if(in) bzero(out, N); if(in) bzero(out, N);
SCRN_Data(); SCRN_Data();
SCRN_RST_set(0); SCRN_CS_set(0);
uint32_t r = 0; uint32_t r = 0;
do{ do{
if(!spi_write_dma((const uint8_t*)out, in, N)) break; 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; else r = 1;
}while(0); }while(0);
SCRN_Command(); SCRN_Command();
SCRN_RST_set(1); SCRN_CS_set(1);
return r; 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){ int ili9341_readregdma(uint8_t reg, uint8_t *data, uint32_t N){
SCRN_Command(); SCRN_Command();
SCRN_RST_set(0); SCRN_CS_set(0);
int r = 0; int r = 0;
do{ do{
if(!spi_write(&reg, 1)) break; if(!spi_write(&reg, 1)) break;

View File

@ -173,6 +173,8 @@
extern uint16_t colorbuf[]; extern uint16_t colorbuf[];
int ili9341_init(); int ili9341_init();
int ili9341_on();
int ili9341_off();
int ili9341_readreg(uint8_t reg, uint8_t *data, uint32_t N); 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_writereg(uint8_t reg, const uint8_t *data, uint32_t N);
int ili9341_writereg16(uint8_t reg, uint16_t data); int ili9341_writereg16(uint8_t reg, uint16_t data);

View File

@ -0,0 +1,32 @@
/*
* This file is part of the nitrogen project.
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#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();

View File

@ -0,0 +1,188 @@
/*
* This file is part of the nitrogen project.
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
*
* 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 <http://www.gnu.org/licenses/>.
*/
#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<<i;
}
// now check all buttons
if(evtmask & 1<<0){ // escape to main window or force refresh
if(dispstate == DISP_MENU){
dispstate = DISP_MAINWIN;
}
lastTmeas = Tms - SENSORS_DATA_TIMEOUT*2; // force refresh
}
if(dispstate == DISP_MENU){ // buttons 'up'/'down' works only in menu mode
if(evtmask & 1<<1){ // up
;
}
if(evtmask & 1<<2){ // down
;
}
}
if(evtmask & 1<<3){ // select/menu
if(dispstate == DISP_MAINWIN){ // switch to menu mode
dispstate = DISP_MENU;
refresh_menu();
}else{ // select
;
}
}
}
void indication_process(){
if(!LEDsON) return;
leds_proc();
btns_proc();
switch(dispstate){
case DISP_MAINWIN:
if(Tms - lastTmeas > SENSORS_DATA_TIMEOUT){
refresh_mainwin();
lastTmeas = Tms;
}
break;
case DISP_MENU: // do nothing
;
break;
}
}

View File

@ -18,11 +18,13 @@
#include "adc.h" #include "adc.h"
#include "BMP280.h" #include "BMP280.h"
//#include "buttons.h" #include "buttons.h"
//#include "can.h" //#include "can.h"
//#include "flash.h" //#include "flash.h"
#include "hardware.h" #include "hardware.h"
#include "i2c.h" #include "i2c.h"
#include "ili9341.h"
#include "incication.h"
#include "proto.h" #include "proto.h"
#include "screen.h" #include "screen.h"
#include "strfunc.h" #include "strfunc.h"
@ -54,14 +56,9 @@ int main(void){
adc_setup(); adc_setup();
BMP280_setup(0); BMP280_setup(0);
USBPU_ON(); USBPU_ON();
uint32_t ctr = 0;
// CAN_message *can_mesg; // CAN_message *can_mesg;
while(1){ while(1){
IWDG->KR = IWDG_REFRESH; IWDG->KR = IWDG_REFRESH;
if(Tms - ctr > 499){
ctr = Tms;
LED_blink(0);
}
/*CAN_proc(); /*CAN_proc();
if(CAN_get_status() == CAN_FIFO_OVERRUN){ if(CAN_get_status() == CAN_FIFO_OVERRUN){
USB_sendstr("CAN bus fifo overrun occured!\n"); 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 //i2c_have_DMA_Rx(); // check if there's DMA Rx complete
BMP280_process(); 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); int l = USB_receivestr(inbuff, MAXSTRLEN);
if(l < 0) USB_sendstr("ERROR: USB buffer overflow or string was too long\n"); if(l < 0) USB_sendstr("ERROR: USB buffer overflow or string was too long\n");
else if(l){ else if(l){
@ -116,6 +98,20 @@ int main(void){
if(ans) USB_sendstr(ans); if(ans) USB_sendstr(ans);
} }
process_screen(); 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();
}
}
} }
} }

View File

@ -24,6 +24,8 @@ i2c.c
i2c.h i2c.h
ili9341.c ili9341.c
ili9341.h ili9341.h
incication.h
indication.c
main.c main.c
pdnuart.c pdnuart.c
pdnuart.h pdnuart.h

Before

Width:  |  Height:  |  Size: 457 B

After

Width:  |  Height:  |  Size: 483 B

View File

@ -17,6 +17,7 @@
*/ */
#include "adc.h" #include "adc.h"
#include "buttons.h"
#include "BMP280.h" #include "BMP280.h"
#include "hardware.h" #include "hardware.h"
#include "i2c.h" #include "i2c.h"
@ -70,8 +71,8 @@ static void sendkeyuhex(const char *cmd, int parno, uint32_t u){
static int leds(const char *cmd, int parno, const char *c, int32_t i){ static int leds(const char *cmd, int parno, const char *c, int32_t i){
if(parno < 0){ // enable/disable all if(parno < 0){ // enable/disable all
if(c){ if(c){
LEDsON = (i ? 1 : 0); if(i) LEDS_ON();
if(!LEDsON) for(int _ = 0; _ < 4; ++_) LED_off(_); else LEDS_OFF();
} }
sendkey("LEDon", -1, LEDsON); sendkey("LEDon", -1, LEDsON);
}else{ }else{
@ -212,12 +213,12 @@ static int scrndcr(const char *cmd, int _U_ parno, const char *c, int32_t i){
} }
sendkeyu(cmd, -1, SCRN_DCX_get()); sendkeyu(cmd, -1, SCRN_DCX_get());
return RET_GOOD; return RET_GOOD;
} }/*
static int scrnrst(const char *cmd, int _U_ parno, const char *c, int32_t i){ static int scrnrst(const char *cmd, int _U_ parno, const char *c, int32_t i){
if(c) SCRN_RST_set(i); if(c) SCRN_CS_set(i);
sendkeyu(cmd, -1, SCRN_RST_get()); sendkeyu(cmd, -1, SCRN_CS_get());
return RET_GOOD; return RET_GOOD;
} }*/
static int scrnrdwr(const char *cmd, int parno, const char *c, int32_t i){ static int scrnrdwr(const char *cmd, int parno, const char *c, int32_t i){
if(parno < 0 || parno > 255) return RET_WRONGPARNO; if(parno < 0 || parno > 255) return RET_WRONGPARNO;
if(c){ if(c){
@ -271,7 +272,13 @@ static int scrninit(const char _U_ *cmd, int _U_ parno, const char _U_ *c, int32
USB_sendstr(OK); USB_sendstr(OK);
return RET_GOOD; 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){ static int scrnfill(const char *cmd, int parno, const char *c, int32_t i){
if(parno < 0) parno = RGB(0xf, 0x1f, 0xf); if(parno < 0) parno = RGB(0xf, 0x1f, 0xf);
if(parno > 0xffff) return RET_WRONGPARNO; 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); sendkeyuhex(cmd, parno, i);
return RET_GOOD; 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){ static int scolor(const char *cmd, int parno, const char *c, int32_t i){
// fg=bg, default: fg=0xffff, bg=0 // fg=bg, default: fg=0xffff, bg=0
if(parno < 0 || parno > 0xffff) parno = 0xffff; 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; 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{ typedef struct{
int (*fn)(const char*, int, const char*, int32_t); int (*fn)(const char*, int, const char*, int32_t);
@ -393,8 +416,9 @@ commands cmdlist[] = {
{NULL, "Different commands", NULL}, {NULL, "Different commands", NULL},
{bme, "BME", "get pressure, temperature and humidity"}, {bme, "BME", "get pressure, temperature and humidity"},
{bmefilter, "BMEf", "set filter (0..4)"}, {bmefilter, "BMEf", "set filter (0..4)"},
{buttons, "button", "get buttonx state"},
{buzzer, "buzzer", "get/set (0 - off, 1 - on) buzzer"}, {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)"}, {pwm, "pwm", "set/get x channel (0..3) pwm value (0..100)"},
{reset, "reset", "reset MCU"}, {reset, "reset", "reset MCU"},
{tms, "tms", "print Tms"}, {tms, "tms", "print Tms"},
@ -406,7 +430,7 @@ commands cmdlist[] = {
{NULL, "Screen commands", NULL}, {NULL, "Screen commands", NULL},
{scrnled, "Sled", "turn on/off screen lights"}, {scrnled, "Sled", "turn on/off screen lights"},
{scrndcr, "Sdcr", "set data(1)/command(0)"}, {scrndcr, "Sdcr", "set data(1)/command(0)"},
{scrnrst, "Srst", "reset (1/0)"}, // {scrnrst, "Srst", "reset (1/0)"},
{scrnrdwr, "Sreg", "read/write 8-bit register"}, {scrnrdwr, "Sreg", "read/write 8-bit register"},
{scrnrdwr4, "Sregx", "read/write 32-bit register"}, {scrnrdwr4, "Sregx", "read/write 32-bit register"},
{scrnrdn, "Sregn", "read from register x =n bytes"}, {scrnrdn, "Sregn", "read from register x =n bytes"},
@ -415,12 +439,14 @@ commands cmdlist[] = {
{scrndata4, "Sdatn", "write x bytes of =data"}, {scrndata4, "Sdatn", "write x bytes of =data"},
{sread, "Sread", "read "}, {sread, "Sread", "read "},
{scrninit, "Sini", "init screen"}, {scrninit, "Sini", "init screen"},
{scrnonoff, "Spower", "=0 - off, =1 - on"},
{scrnfill, "Sfill", "fill screen with color (=npix)"}, {scrnfill, "Sfill", "fill screen with color (=npix)"},
{scrnfilln, "Sfilln", "fill screen (next) with color (=npix)"}, {scrnfilln, "Sfilln", "fill screen (next) with color (=npix)"},
{smadctl, "Smad", "change MADCTL"}, {smadctl, "Smad", "change MADCTL"},
{scol, "Scol", "set column limits (low=high)"}, {scol, "Scol", "set column limits (low=high)"},
{srow, "Srow", "set row limits (low=high)"}, {srow, "Srow", "set row limits (low=high)"},
{scls, "Scls", "clear screen fg=bg"}, {scls, "Scls", "clear screen fg=bg"},
{srefr, "Srefresh", "refresh full screen"},
{scolor, "Scolor", "seg color fg=bg"}, {scolor, "Scolor", "seg color fg=bg"},
{sputstr, "Sstr", "put string y=string"}, {sputstr, "Sstr", "put string y=string"},
{sstate, "Sstate", "current screen state"}, {sstate, "Sstate", "current screen state"},

View File

@ -90,7 +90,6 @@ void ClearScreen(){
foreground[i] = fgColor; foreground[i] = fgColor;
background[i] = bgColor; background[i] = bgColor;
} }
for(int i = SPRITE_SZ-40; i < SPRITE_SZ; ++i) foreground[i] = i;
UpdateScreen(0, SCRNH-1); UpdateScreen(0, SCRNH-1);
} }
@ -199,7 +198,7 @@ int strpixlen(const char *str){
const uint8_t *c = font_char(*str++); const uint8_t *c = font_char(*str++);
if(c) l += *c; if(c) l += *c;
} }
return l; return l * fontscale;
} }
// convert buffer to update (return 0 if all sent) // convert buffer to update (return 0 if all sent)

View File

@ -42,6 +42,52 @@ typedef enum{ // screen states
// maximal font scale // maximal font scale
#define FONTSCALEMAX (10) #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(); screen_state getScreenState();
void ClearScreen(); void ClearScreen();
void UpdateScreen(int y0, int y1); void UpdateScreen(int y0, int y1);

View File

@ -1,2 +1,2 @@
#define BUILD_NUMBER "242" #define BUILD_NUMBER "253"
#define BUILD_DATE "2023-05-11" #define BUILD_DATE "2023-05-12"

View File

@ -48,7 +48,7 @@ LIB_DIR := $(INC_DIR)/ld
############################################################################### ###############################################################################
# C flags # C flags
CFLAGS += -O2 -D__thumb2__=1 -MD CFLAGS += -O2 -D__thumb2__=1 -MD
CFLAGS += -Wall -Wextra -Wshadow CFLAGS += -Wall -Wextra -Wshadow -Wdouble-promotion
CFLAGS += -fshort-enums -ffunction-sections -fdata-sections CFLAGS += -fshort-enums -ffunction-sections -fdata-sections
#CFLAGS += -fno-common -fno-stack-protector #CFLAGS += -fno-common -fno-stack-protector
CFLAGS += $(ARCH_FLAGS) CFLAGS += $(ARCH_FLAGS)