usbcan_relay: add standalone buttons reactions

This commit is contained in:
Edward Emelianov 2021-09-10 12:06:01 +03:00
parent 50fdc3e104
commit 1c4c7d9636
91 changed files with 200 additions and 547 deletions

0
F0-nolib/CANbus_stepper/src/canstepper.bin Executable file → Normal file
View File

0
F0-nolib/Chiller/chiller.bin Executable file → Normal file
View File

0
F0-nolib/F0_testbrd/pl2303.bin Executable file → Normal file
View File

0
F0-nolib/QuadEncoder/encoder.bin Executable file → Normal file
View File

0
F0-nolib/Servo/servo.bin Executable file → Normal file
View File

0
F0-nolib/Socket_fans/sockfans.bin Executable file → Normal file
View File

0
F0-nolib/TM1637/tm1637.bin Executable file → Normal file
View File

0
F0-nolib/USBHID/usbhid.bin Executable file → Normal file
View File

0
F0-nolib/USB_pl2303_snippet/usb.bin Executable file → Normal file
View File

0
F0-nolib/blink/blink.bin Normal file → Executable file
View File

0
F0-nolib/canbus/src/canbus.bin Executable file → Normal file
View File

0
F0-nolib/htu21d_nucleo/usart.bin Executable file → Normal file
View File

View File

@ -1 +1 @@
/home/eddy/Yandex.Disk/Projects/stm32samples/F0-nolib/inc/Fx Fx

View File

@ -453,7 +453,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void)
*/ */
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
{ {
__ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp"); __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack));
} }

0
F0-nolib/morze/morze.bin Executable file → Normal file
View File

0
F0-nolib/pl2303/pl2303.bin Executable file → Normal file
View File

0
F0-nolib/tsys01_nucleo/tsys01.bin Executable file → Normal file
View File

0
F0-nolib/uart_blink/uartblink.bin Executable file → Normal file
View File

0
F0-nolib/uart_blink_dma/uartblink.bin Executable file → Normal file
View File

0
F0-nolib/uart_nucleo/usart.bin Executable file → Normal file
View File

View File

@ -48,14 +48,25 @@ CAN_status CAN_get_status(){
#ifdef EBUG #ifdef EBUG
if(st == CAN_FIFO_OVERRUN) MSG("fifo 0 overrun\n"); if(st == CAN_FIFO_OVERRUN) MSG("fifo 0 overrun\n");
#endif #endif
if(st == CAN_FIFO_OVERRUN) can_status = CAN_READY; if(st == CAN_FIFO_OVERRUN){
SEND("FIFO overrun\n");
can_status = CAN_READY;
}
return st; return st;
} }
// push next message into buffer; return 1 if buffer overfull // push next message into buffer; return 1 if buffer overfull
static int CAN_messagebuf_push(CAN_message *msg){ static int CAN_messagebuf_push(CAN_message *msg){
//MSG("Try to push\n"); //MSG("Try to push\n");
if(first_free_idx == first_nonfree_idx) return 1; // no free space #ifdef EBUG
SEND("push\n");
#endif
if(first_free_idx == first_nonfree_idx){
#ifdef EBUG
SEND("INBUF OVERFULL\n");
#endif
return 1; // no free space
}
if(first_nonfree_idx < 0) first_nonfree_idx = 0; // first message in empty buffer if(first_nonfree_idx < 0) first_nonfree_idx = 0; // first message in empty buffer
memcpy(&messages[first_free_idx++], msg, sizeof(CAN_message)); memcpy(&messages[first_free_idx++], msg, sizeof(CAN_message));
// need to roll? // need to roll?
@ -287,6 +298,9 @@ static void can_process_fifo(uint8_t fifo_num){
LED_on(LED1); // Turn on LED1 - message received LED_on(LED1); // Turn on LED1 - message received
CAN_FIFOMailBox_TypeDef *box = &CAN->sFIFOMailBox[fifo_num]; CAN_FIFOMailBox_TypeDef *box = &CAN->sFIFOMailBox[fifo_num];
volatile uint32_t *RFxR = (fifo_num) ? &CAN->RF1R : &CAN->RF0R; volatile uint32_t *RFxR = (fifo_num) ? &CAN->RF1R : &CAN->RF0R;
#ifdef EBUG
printu(*RFxR & CAN_RF0R_FMP0); SEND(" messages in FIFO\n");
#endif
// read all // read all
while(*RFxR & CAN_RF0R_FMP0){ // amount of messages pending while(*RFxR & CAN_RF0R_FMP0){ // amount of messages pending
// CAN_RDTxR: (16-31) - timestamp, (8-15) - filter match index, (0-3) - data length // CAN_RDTxR: (16-31) - timestamp, (8-15) - filter match index, (0-3) - data length
@ -334,6 +348,13 @@ static void can_process_fifo(uint8_t fifo_num){
} }
void cec_can_isr(){ void cec_can_isr(){
/*
if(CAN->RF0R & CAN_RF0R_FOVR0){
can_process_fifo(0);
}
if(CAN->RF1R & CAN_RF1R_FOVR1){
can_process_fifo(1);
}*/
if(CAN->RF0R & CAN_RF0R_FOVR0){ // FIFO overrun if(CAN->RF0R & CAN_RF0R_FOVR0){ // FIFO overrun
CAN->RF0R &= ~CAN_RF0R_FOVR0; CAN->RF0R &= ~CAN_RF0R_FOVR0;
can_status = CAN_FIFO_OVERRUN; can_status = CAN_FIFO_OVERRUN;

View File

@ -76,7 +76,9 @@ int main(void){
USB_setup(); USB_setup();
CAN_setup(100); CAN_setup(100);
RCC->CSR |= RCC_CSR_RMVF; // remove reset flags RCC->CSR |= RCC_CSR_RMVF; // remove reset flags
#ifndef EBUG
iwdg_setup(); iwdg_setup();
#endif
while (1){ while (1){
IWDG->KR = IWDG_REFRESH; // refresh watchdog IWDG->KR = IWDG_REFRESH; // refresh watchdog
@ -90,7 +92,7 @@ int main(void){
SEND("CAN bus fifo overrun occured!\n"); SEND("CAN bus fifo overrun occured!\n");
sendbuf(); sendbuf();
} }
can_mesg = CAN_messagebuf_pop(); while((can_mesg = CAN_messagebuf_pop())){
if(can_mesg && isgood(can_mesg->ID)){ if(can_mesg && isgood(can_mesg->ID)){
LED_on(LED0); LED_on(LED0);
lastT = Tms; lastT = Tms;
@ -108,6 +110,7 @@ int main(void){
newline(); sendbuf(); newline(); sendbuf();
} }
} }
}
if((txt = get_USB())){ if((txt = get_USB())){
IWDG->KR = IWDG_REFRESH; IWDG->KR = IWDG_REFRESH;
cmd_parser(txt); cmd_parser(txt);

Binary file not shown.

View File

@ -19,3 +19,13 @@ Pinout:
- PB12..15 - LED0..3 outputs (direct outputs without any protection!!!) - PB12..15 - LED0..3 outputs (direct outputs without any protection!!!)
The pins LEDr0 and LEDr1 are indicated relay works (12V through 2.2kOhm resistor) The pins LEDr0 and LEDr1 are indicated relay works (12V through 2.2kOhm resistor)
### Buttons standalone
BTN1 - switch relay1
BTN2 - switch relay 2
BTN3 - change PWM0: hold to turn ON or turn OFF; press shortly BTN1/BTN2 to increase/decrease PWM0 to 1,
hold BTN1/BTN2 to inc/dec PWM0 to 25 (do as many presses as need).

View File

@ -27,6 +27,8 @@ typedef struct{
static keybase allkeys[BTNSNO] = {0}; // array for buttons' states static keybase allkeys[BTNSNO] = {0}; // array for buttons' states
uint32_t lastUnsleep = 0; // last keys activity time
void process_keys(){ void process_keys(){
static uint32_t lastT = 0; static uint32_t lastT = 0;
if(Tms == lastT) return; if(Tms == lastT) return;
@ -61,6 +63,7 @@ void process_keys(){
} }
if(e != k->event){ if(e != k->event){
k->lastTms = Tms; k->lastTms = Tms;
lastUnsleep = Tms;
} }
} }
} }
@ -79,3 +82,9 @@ keyevent keystate(uint8_t k, uint32_t *T){
if(T) *T = allkeys[k].lastTms; if(T) *T = allkeys[k].lastTms;
return evt; return evt;
} }
// getter of keyevent for allkeys[]
keyevent keyevt(uint8_t k){
if(k >= BTNSNO) return EVT_NONE;
return allkeys[k].event;
}

View File

@ -37,6 +37,7 @@ extern uint32_t lastUnsleep; // last keys activity time
void process_keys(); void process_keys();
keyevent keystate(uint8_t k, uint32_t *T); keyevent keystate(uint8_t k, uint32_t *T);
keyevent keyevt(uint8_t k);
#define BUTTONS_H__ #define BUTTONS_H__
#endif // BUTTONS_H__ #endif // BUTTONS_H__

View File

@ -27,7 +27,7 @@
static CAN_message messages[CAN_INMESSAGE_SIZE]; static CAN_message messages[CAN_INMESSAGE_SIZE];
static uint8_t first_free_idx = 0; // index of first empty cell static uint8_t first_free_idx = 0; // index of first empty cell
static int8_t first_nonfree_idx = -1; // index of first data cell static int8_t first_nonfree_idx = -1; // index of first data cell
static uint16_t oldspeed = 100; // speed of last init static uint16_t oldspeed = DEFAULT_CAN_SPEED; // speed of last init
#ifdef EBUG #ifdef EBUG
static uint32_t last_err_code = 0; static uint32_t last_err_code = 0;
@ -42,10 +42,6 @@ static CAN_message *flood_msg = NULL; // == loc_flood_msg - to flood
CAN_status CAN_get_status(){ CAN_status CAN_get_status(){
CAN_status st = can_status; CAN_status st = can_status;
// give overrun message only once
#ifdef EBUG
if(st == CAN_FIFO_OVERRUN) MSG("fifo 0 overrun\n");
#endif
if(st == CAN_FIFO_OVERRUN) can_status = CAN_READY; if(st == CAN_FIFO_OVERRUN) can_status = CAN_READY;
return st; return st;
} }
@ -214,9 +210,7 @@ CAN_status can_send(uint8_t *msg, uint8_t len, uint16_t target_id){
if(CAN->TSR & (CAN_TSR_TME)){ if(CAN->TSR & (CAN_TSR_TME)){
mailbox = (CAN->TSR & CAN_TSR_CODE) >> 24; mailbox = (CAN->TSR & CAN_TSR_CODE) >> 24;
}else{ // no free mailboxes }else{ // no free mailboxes
#ifdef EBUG //SEND("No free mailboxes"); NL();
MSG("No free mailboxes"); NL();
#endif
return CAN_BUSY; return CAN_BUSY;
} }
#ifdef EBUG #ifdef EBUG
@ -313,7 +307,7 @@ static void can_process_fifo(uint8_t fifo_num){
} }
} }
if(msg.ID == CANID) parseCANcommand(&msg); if(msg.ID == CANID) parseCANcommand(&msg);
else if(CAN_messagebuf_push(&msg)) return; // error: buffer is full, try later if(CAN_messagebuf_push(&msg)) return; // error: buffer is full, try later
*RFxR |= CAN_RF0R_RFOM0; // release fifo for access to next message *RFxR |= CAN_RF0R_RFOM0; // release fifo for access to next message
} }
//if(*RFxR & CAN_RF0R_FULL0) *RFxR &= ~CAN_RF0R_FULL0; //if(*RFxR & CAN_RF0R_FULL0) *RFxR &= ~CAN_RF0R_FULL0;

View File

@ -36,7 +36,7 @@
* CAN_CMD_LED: data[1] = LEDs state (bits 0..3 for LEDs number 0..3) * CAN_CMD_LED: data[1] = LEDs state (bits 0..3 for LEDs number 0..3)
* CAN_CMD_MCU: data[2,3] = int16_t MCUT*10, data[4,5] = uint16_t Vdd*100 (LITTLE endian!) * CAN_CMD_MCU: data[2,3] = int16_t MCUT*10, data[4,5] = uint16_t Vdd*100 (LITTLE endian!)
* CAN_CMD_PWM: data[1..3] = pwm value for each channel (0..2) * CAN_CMD_PWM: data[1..3] = pwm value for each channel (0..2)
* CAN_CMD_RELAY: data[0] = (bits 0 & 1) - state of relay N] * CAN_CMD_RELAY: data[1] = (bits 0 & 1) - state of relay N]
* CAN_CMD_TMS: data[4..7] = Tms (LITTLE endian!) * CAN_CMD_TMS: data[4..7] = Tms (LITTLE endian!)
*/ */
@ -56,13 +56,19 @@ TRUE_INLINE uint8_t ADCget(uint8_t values[8]){
TRUE_INLINE void BTNSget(uint8_t values[8]){ TRUE_INLINE void BTNSget(uint8_t values[8]){
uint32_t T; uint32_t T;
for(uint8_t i = 0; i < BTNSNO; ++i){ uint8_t start = 0, stop = BTNSNO;
if(values[1] < BTNSNO){ // check only one button
start = values[1]; stop = start + 1;
}
for(uint8_t i = start; i < stop; ++i){
values[1] = i; values[1] = i;
values[2] = keystate(i, &T); values[2] = keystate(i, &T);
values[3] = 0; values[3] = 0;
*((uint32_t*)&values[4]) = T; *((uint32_t*)&values[4]) = T;
int N = 1000; T = Tms;
while(CAN_BUSY == can_send(values, 8, OUTPID)) if(--N == 0) break; while(CAN_BUSY == can_send(values, 8, OUTPID)){
if(Tms - T > 5) break;
}
} }
} }
@ -141,22 +147,24 @@ void parseCANcommand(CAN_message *msg){
len = ADCget(outpdata); len = ADCget(outpdata);
break; break;
case CAN_CMD_BTNS: case CAN_CMD_BTNS:
if(msg->length == 2) outpdata[1] = msg->data[1]; // check only one button
else outpdata[1] = BTNSNO;
BTNSget(outpdata); BTNSget(outpdata);
return; return;
break; break;
case CAN_CMD_LED: case CAN_CMD_LED:
if(setter) LEDSset(msg->data); if(setter && msg->length > 1) LEDSset(msg->data);
len = LEDSget(outpdata); len = LEDSget(outpdata);
break; break;
case CAN_CMD_MCU: case CAN_CMD_MCU:
len = MCUget(outpdata); len = MCUget(outpdata);
break; break;
case CAN_CMD_PWM: case CAN_CMD_PWM:
if(setter) PWMset(msg->data); if(setter && msg->length > 3) PWMset(msg->data);
len = PWMget(outpdata); len = PWMget(outpdata);
break; break;
case CAN_CMD_RELAY: case CAN_CMD_RELAY:
if(setter) Rset(msg->data); if(setter && msg->length > 1) Rset(msg->data);
len = Rget(outpdata); len = Rget(outpdata);
break; break;
case CAN_CMD_TMS: case CAN_CMD_TMS:

View File

@ -40,7 +40,7 @@ typedef enum{
} CAN_commands; } CAN_commands;
// output messages identifier // output messages identifier
#define OUTPID (CANID + 0x100) #define OUTPID (CANID)
void parseCANcommand(CAN_message *msg); void parseCANcommand(CAN_message *msg);

View File

@ -0,0 +1,67 @@
/*
* This file is part of the canrelay project.
* Copyright 2021 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/>.
*/
// custom standalone buttons reaction
#include <stm32f0.h>
#include "buttons.h"
#include "custom_buttons.h"
#include "hardware.h"
/*
* check buttons, on long press of button:
* 1 - switch relay1
* 2 - switch relay2
* 3 - work with PWM out 0 (when btn3 pressed, btn1 increased & btn2 decreased PWM width)
* press once btn2/3 to change PWM @1, hold to change @25 (repeat as many times as need)
*/
void custom_buttons_process(){
static uint32_t lastT = 0;
static uint8_t pwmval = 127;
static uint8_t trig = 0; // == 1 if given btn3 was off
if(lastUnsleep == lastT) return; // no buttons activity
lastT = lastUnsleep;
if(keyevt(3) == EVT_HOLD){ // PWM
if(keyevt(2) == EVT_HOLD){ // decrease PWM by 25
if(pwmval > 25) pwmval -= 25;
else pwmval = 0;
}else if(keyevt(2) == EVT_PRESS){ // decrease PWM by 1
if(pwmval > 0) --pwmval;
}else if(keyevt(1) == EVT_HOLD){ // increase PWM by 25
if(pwmval < 230) pwmval += 25;
else pwmval = 255;
}else if(keyevt(1) == EVT_PRESS){
if(pwmval < 254) ++pwmval;
}
if(trig == 0){ // first hold after release
if(TIM1->CCR1) TIM1->CCR1 = 0; // turn off if was ON
else{
TIM1->CCR1 = pwmval;
trig = 1;
}
}else TIM1->CCR1 = pwmval;
return;
}else trig = 0;
if(keyevt(1) == EVT_HOLD){ // relay1
Relay_TGL(0);
}
if(keyevt(2) == EVT_HOLD){ // relay2
Relay_TGL(1);
}
}

View File

@ -0,0 +1,25 @@
/*
* This file is part of the canrelay project.
* Copyright 2021 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
#ifndef CUSTOM_BUTTONS_H__
#define CUSTOM_BUTTONS_H__
void custom_buttons_process();
#endif // CUSTOM_BUTTONS_H__

View File

@ -22,6 +22,9 @@
#include <stm32f0.h> #include <stm32f0.h>
// default CAN bus speed in kbaud
#define DEFAULT_CAN_SPEED (250)
#define SYSMEM03x 0x1FFFEC00 #define SYSMEM03x 0x1FFFEC00
#define SYSMEM04x 0x1FFFC400 #define SYSMEM04x 0x1FFFC400
#define SYSMEM05x 0x1FFFEC00 #define SYSMEM05x 0x1FFFEC00
@ -55,6 +58,7 @@ extern GPIO_TypeDef *R_ports[RelaysNO];
extern const uint32_t R_pins[RelaysNO]; extern const uint32_t R_pins[RelaysNO];
#define Relay_ON(x) do{pin_set(R_ports[x], R_pins[x]);}while(0) #define Relay_ON(x) do{pin_set(R_ports[x], R_pins[x]);}while(0)
#define Relay_OFF(x) do{pin_clear(R_ports[x], R_pins[x]);}while(0) #define Relay_OFF(x) do{pin_clear(R_ports[x], R_pins[x]);}while(0)
#define Relay_TGL(x) do{pin_toggle(R_ports[x], R_pins[x]);}while(0)
#define Relay_chk(x) (pin_read(R_ports[x], R_pins[x])) #define Relay_chk(x) (pin_read(R_ports[x], R_pins[x]))
// Buttons amount // Buttons amount

View File

@ -19,6 +19,7 @@
#include "adc.h" #include "adc.h"
#include "buttons.h" #include "buttons.h"
#include "can.h" #include "can.h"
#include "custom_buttons.h"
#include "hardware.h" #include "hardware.h"
#include "proto.h" #include "proto.h"
#include "usb.h" #include "usb.h"
@ -74,20 +75,21 @@ int main(void){
adc_setup(); adc_setup();
tim1_setup(); tim1_setup();
USB_setup(); USB_setup();
CAN_setup(100); CAN_setup(DEFAULT_CAN_SPEED);
RCC->CSR |= RCC_CSR_RMVF; // remove reset flags RCC->CSR |= RCC_CSR_RMVF; // remove reset flags
iwdg_setup(); iwdg_setup();
while (1){ while (1){
IWDG->KR = IWDG_REFRESH; // refresh watchdog IWDG->KR = IWDG_REFRESH; // refresh watchdog
process_keys(); process_keys();
custom_buttons_process();
can_proc(); can_proc();
usb_proc(); usb_proc();
if(CAN_get_status() == CAN_FIFO_OVERRUN){ if(CAN_get_status() == CAN_FIFO_OVERRUN){
SEND("CAN bus fifo overrun occured!\n"); SEND("CAN bus fifo overrun occured!\n");
sendbuf(); sendbuf();
} }
can_mesg = CAN_messagebuf_pop(); while((can_mesg = CAN_messagebuf_pop())){
if(can_mesg && isgood(can_mesg->ID)){ if(can_mesg && isgood(can_mesg->ID)){
if(ShowMsgs){ // new data in buff if(ShowMsgs){ // new data in buff
IWDG->KR = IWDG_REFRESH; IWDG->KR = IWDG_REFRESH;
@ -102,6 +104,7 @@ int main(void){
newline(); sendbuf(); newline(); sendbuf();
} }
} }
}
if((txt = get_USB())){ if((txt = get_USB())){
IWDG->KR = IWDG_REFRESH; IWDG->KR = IWDG_REFRESH;
cmd_parser(txt); cmd_parser(txt);

Binary file not shown.

0
F0/blink/blink.bin Executable file → Normal file
View File

0
F0/uart/uart.bin Executable file → Normal file
View File

0
F1-nolib/BMP180/BMP180.bin Executable file → Normal file
View File

0
F1-nolib/BMP280/BMP280.bin Executable file → Normal file
View File

0
F1-nolib/CDC_ACM/cdcacm.bin Executable file → Normal file
View File

0
F1-nolib/DHT22_DHT11/DHT22.bin Executable file → Normal file
View File

0
F1-nolib/DS18/DS18.bin Executable file → Normal file
View File

0
F1-nolib/F1_testbrd/pl2303.bin Executable file → Normal file
View File

0
F1-nolib/I2Cscan/I2Cscan.bin Executable file → Normal file
View File

0
F1-nolib/LED_Screen/LEDscreen.bin Executable file → Normal file
View File

0
F1-nolib/LED_Screen/genlist Executable file → Normal file
View File

0
F1-nolib/LED_Screen/scrtest/scrtest Executable file → Normal file
View File

0
F1-nolib/MAX7219_screen/MAX7219.bin Executable file → Normal file
View File

0
F1-nolib/PL2303/pl2303.bin Executable file → Normal file
View File

0
F1-nolib/RGB_LED_Screen/RGBLEDscreen.bin Executable file → Normal file
View File

0
F1-nolib/RGB_LED_Screen/getrand Executable file → Normal file
View File

View File

@ -1,301 +0,0 @@
/*
* This file is part of the RGBLEDscreen project.
* Copyright 2020 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 "adcrandom.h"
#include "balls.h"
#include "fonts.h"
#include "proto.h"
#include "screen.h"
#include "usb.h"
extern uint8_t countms, rainbow, balls;
extern uint32_t Tms;
char *omit_spaces(const char *buf){
while(*buf){
if(*buf > ' ') break;
++buf;
}
return (char*)buf;
}
// In case of overflow return `buf` and N==0xffffffff
// read decimal number & return pointer to next non-number symbol
static char *getdec(const char *buf, uint32_t *N){
char *start = (char*)buf;
uint32_t num = 0;
while(*buf){
char c = *buf;
if(c < '0' || c > '9'){
break;
}
if(num > 429496729 || (num == 429496729 && c > '5')){ // overflow
*N = 0xffffff;
return start;
}
num *= 10;
num += c - '0';
++buf;
}
*N = num;
return (char*)buf;
}
// read hexadecimal number (without 0x prefix!)
static char *gethex(const char *buf, uint32_t *N){
char *start = (char*)buf;
uint32_t num = 0;
while(*buf){
char c = *buf;
uint8_t M = 0;
if(c >= '0' && c <= '9'){
M = '0';
}else if(c >= 'A' && c <= 'F'){
M = 'A' - 10;
}else if(c >= 'a' && c <= 'f'){
M = 'a' - 10;
}
if(M){
if(num & 0xf0000000){ // overflow
*N = 0xffffff;
return start;
}
num <<= 4;
num += c - M;
}else{
break;
}
++buf;
}
*N = num;
return (char*)buf;
}
// read octal number (without 0 prefix!)
static char *getoct(const char *buf, uint32_t *N){
char *start = (char*)buf;
uint32_t num = 0;
while(*buf){
char c = *buf;
if(c < '0' || c > '7'){
break;
}
if(num & 0xe0000000){ // overflow
*N = 0xffffff;
return start;
}
num <<= 3;
num += c - '0';
++buf;
}
*N = num;
return (char*)buf;
}
// read binary number (without b prefix!)
static char *getbin(const char *buf, uint32_t *N){
char *start = (char*)buf;
uint32_t num = 0;
while(*buf){
char c = *buf;
if(c < '0' || c > '1'){
break;
}
if(num & 0x80000000){ // overflow
*N = 0xffffff;
return start;
}
num <<= 1;
if(c == '1') num |= 1;
++buf;
}
*N = num;
return (char*)buf;
}
/**
* @brief getnum - read uint32_t from string (dec, hex or bin: 127, 0x7f, 0b1111111)
* @param buf - buffer with number and so on
* @param N - the number read
* @return pointer to first non-number symbol in buf
* (if it is == buf, there's no number or if *N==0xffffffff there was overflow)
*/
char *getnum(const char *txt, uint32_t *N){
char *nxt = NULL;
char *s = omit_spaces(txt);
if(*s == '0'){ // hex, oct or 0
if(s[1] == 'x' || s[1] == 'X'){ // hex
nxt = gethex(s+2, N);
if(nxt == s+2) nxt = (char*)txt;
}else if(s[1] > '0'-1 && s[1] < '8'){ // oct
nxt = getoct(s+1, N);
if(nxt == s+1) nxt = (char*)txt;
}else{ // 0
nxt = s+1;
*N = 0;
}
}else if(*s == 'b' || *s == 'B'){
nxt = getbin(s+1, N);
if(nxt == s+1) nxt = (char*)txt;
}else{
nxt = getdec(s, N);
if(nxt == s) nxt = (char*)txt;
}
return nxt;
}
const char* helpmsg =
"'0/1' - screen off/on\n"
"'2,3' - select font\n"
"'A' - get ADC values\n"
"'B' - start/stop rainBow\n"
"'b' - start/stop Balls\n"
"'C' - clear screen with given color\n"
"'F' - set foreground color\n"
"'G' - get 100 random numbers\n"
"'f' - get FPS\n"
"'R' - software reset\n"
"'W' - test watchdog\n"
"'Zz' -start/stop counting ms\n"
"Any text - put text @ screen\n"
;
const char *parse_cmd(const char *buf){
uint32_t N;
if(buf[1] == '\n'){ // one symbol commands
switch(*buf){
case '0':
ScreenOFF();
return "OFF\n";
break;
case '1':
ScreenON();
return "ON\n";
break;
case '2':
if(choose_font(FONT14)) return "Font14\n";
return "err\n";
break;
case '3':
if(choose_font(FONT16)) return "Font16\n";
return "err\n";
break;
case 'A':
USB_send("Tsens="); USB_send(u2str(getADCval(0)));
USB_send("\nVref="); USB_send(u2str(getADCval(1)));
USB_send("\nRand="); USB_send(u2str(getRand()));
USB_send("\n");
return NULL;
break;
case 'B':
if(rainbow){
rainbow = 0;
return "Stop rainbow\n";
}else{
rainbow = 1;
return "Start rainbow\n";
}
break;
case 'b':
if(balls){
balls = 0;
return "Stop balls\n";
}else{
balls_init();
balls = 1;
return "Start balls\n";
}
case 'f':
if(SCREEN_RELAX == getScreenState()) return "Screen is inactive\n";
USB_send("FPS=");
USB_send(u2str(getFPS()));
USB_send("\n");
return NULL;
break;
case 'G':
/*USB_send(u2str(Tms)); USB_send("\n");
for(int i=0; i < 1000; ++i) getRand();
USB_send(u2str(Tms)); USB_send("\n");*/
for(int i = 0; i < 100; ++i){
USB_send(u2str(getRand()));
USB_send("\n");
}
return NULL;
break;
case 'R':
USB_send("Soft reset\n");
NVIC_SystemReset();
break;
case 'W':
USB_send("Wait for reboot\n");
while(1){nop();};
break;
case 'Z':
countms = 1;
return "Start\n";
break;
case 'z':
countms = 0;
return "Stop\n";
break;
default:
return helpmsg;
}
return NULL;
}else{
switch(*buf){
case 'C':
if(getnum(buf+1, &N)){
ScreenOFF();
setBGcolor(N);
ClearScreen();
ScreenON();
return "Background color\n";
}
return "Wrong color\n";
break;
case 'F':
if(getnum(buf+1, &N)){
setFGcolor(N);
return "Foreground color\n";
}
return "Wrong color\n";
break;
default:
ScreenOFF();
ClearScreen();
PutStringAt(1, curfont->height + 3, buf);
ScreenON();
}
return buf;
}
return NULL;
}
// return string with number `val`
char *u2str(uint32_t val){
static char strbuf[11];
char *bufptr = &strbuf[10];
*bufptr = 0;
if(!val){
*(--bufptr) = '0';
}else{
while(val){
*(--bufptr) = val % 10 + '0';
val /= 10;
}
}
return bufptr;
}

View File

@ -0,0 +1 @@
/home/eddy/Yandex.Disk/Projects/mytakepic/.hg/wcache/checklink-target

0
F1-nolib/SI7005_HTU21D/si7005.bin Executable file → Normal file
View File

0
F1-nolib/SPI/SPI.bin Executable file → Normal file
View File

0
F1-nolib/SevenCDCs/cdcacmcore.bin Executable file → Normal file
View File

0
F1-nolib/Tetris/TETRIS.bin Executable file → Normal file
View File

0
F1-nolib/Tetris/getrand Executable file → Normal file
View File

View File

@ -1,193 +0,0 @@
/*
* This file is part of the TETRIS project.
* Copyright 2021 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 "adcrandom.h"
#include "arkanoid.h"
#include "balls.h"
#include "buttons.h"
#include "fonts.h"
#include "hardware.h"
#include "menu.h"
#include "proto.h"
#include "screen.h"
#include "snake.h"
#include "tetris.h"
#include "usb.h"
#include "usb_lib.h"
// timeout for autosleep (30s)
#define AUTOSLEEP_TMOUT (30000)
volatile uint32_t Tms = 0;
uint8_t balls = 0;
enum{
STATE_MENU,
STATE_SNAKE,
STATE_TETRIS,
STATE_ARKANOID,
STATE_SLEEP,
STATE_GAMEOVER
} curstate = STATE_SLEEP;
/* Called when systick fires */
void sys_tick_handler(void){
++Tms;
}
#define USBBUFSZ (127)
// usb getline
static char *get_USB(){
static char tmpbuf[USBBUFSZ+1], *curptr = tmpbuf;
static int rest = USBBUFSZ;
int x = USB_receive(curptr);
curptr[x] = 0;
if(!x) return NULL;
if(curptr[x-1] == '\n'){
curptr = tmpbuf;
rest = USBBUFSZ;
return tmpbuf;
}
curptr += x; rest -= x;
if(rest <= 0){ // buffer overflow
curptr = tmpbuf;
rest = USBBUFSZ;
USB_send("USB buffer overflow\n");
}
return NULL;
}
static void process_menu(){
switch(menu_activated()){
case MENU_SLEEP:
USB_send("Select 'Sleep'\n");
ScreenOFF();
curstate = STATE_SLEEP;
break;
case MENU_BALLS:
USB_send("Select 'Balls'\n");
if(balls){
balls = 0;
}else{
curstate = STATE_SLEEP;
balls_init();
balls = 1;
}
break;
case MENU_SNAKE:
USB_send("Select 'Snake'\n");
snake_init();
curstate = STATE_SNAKE;
break;
case MENU_TETRIS:
USB_send("Select 'Tetris'\n");
tetris_init();
curstate = STATE_TETRIS;
break;
case MENU_ARKANOID:
USB_send("Select 'Arkanoid'\n");
arkanoid_init();
curstate = STATE_ARKANOID;
default:
break;
}
}
static void gotomenu(){
curstate = STATE_MENU;
clear_events();
show_menu();
}
int main(void){
uint32_t lastT = 0;
sysreset();
StartHSE();
SysTick_Config(72000);
RCC->CSR |= RCC_CSR_RMVF; // remove reset flags
hw_setup();
USBPU_OFF();
adc_setup();
USB_setup();
//iwdg_setup();
USBPU_ON();
keyevent evt;
while(1){
if(Tms - lastT > 499){
LED_blink(LED0);
lastT = Tms;
}
IWDG->KR = IWDG_REFRESH;
if(balls) process_balls();
process_keys();
switch(curstate){
case STATE_SLEEP:
if(keystate(KEY_M, &evt) && evt == EVT_RELEASE){
USB_send("Activate menu\n");
gotomenu();
}
break;
case STATE_MENU:
process_menu();
if(Tms - lastUnsleep > AUTOSLEEP_TMOUT){
USB_send("Autosleep\n");
ScreenOFF();
curstate = STATE_SLEEP;
}
break;
case STATE_SNAKE:
if(!snake_proces()){
show_gameover();
curstate = STATE_GAMEOVER;
}
break;
case STATE_TETRIS:
if(!tetris_process()){
show_gameover();
curstate = STATE_GAMEOVER;
}
break;
case STATE_ARKANOID:
if(!arkanoid_process()){
show_gameover();
curstate = STATE_GAMEOVER;
}
break;
case STATE_GAMEOVER: // show gameover screen
if(keystate(KEY_M, &evt) && evt == EVT_RELEASE){
gotomenu();
}else if(Tms - lastUnsleep > AUTOSLEEP_TMOUT){
USB_send("Autosleep\n");
ScreenOFF();
curstate = STATE_SLEEP;
}
break;
}
usb_proc();
char *txt; const char *ans;
if((txt = get_USB())){
ans = parse_cmd(txt);
if(ans) USB_send(ans);
}
}
return 0;
}

1
F1-nolib/Tetris/main.c Symbolic link
View File

@ -0,0 +1 @@
/home/eddy/Yandex.Disk/Projects/mytakepic/.hg/wcache/checklink-target

0
F1-nolib/USB_HID/usbhid103.bin Executable file → Normal file
View File

0
F1-nolib/chronometer/chrono.bin Normal file → Executable file
View File

0
F1-nolib/chronometer_v2/chrono.bin Executable file → Normal file
View File

0
F1-nolib/chronometer_v3/chrono.bin Executable file → Normal file
View File

View File

@ -453,7 +453,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void)
*/ */
__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
{ {
__ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp"); __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack));
} }

0
F1-nolib/led_blink/blink.bin Executable file → Normal file
View File

0
F1-nolib/pl2303_snippet/pl2303.bin Executable file → Normal file
View File

0
F1-nolib/pl2303_snippet_naked/pl2303.bin Executable file → Normal file
View File

0
F1-nolib/pwmdmatest/pwmtest.bin Executable file → Normal file
View File

0
F1-nolib/pwmtest/pwmtest.bin Executable file → Normal file
View File

0
F1-nolib/uart/uart.bin Executable file → Normal file
View File

0
F1-nolib/ws2815/ws2815.bin Executable file → Normal file
View File

0
F1/1_wire/onewire.bin Executable file → Normal file
View File

0
F1/2.8TFT/dma_gpio.bin Executable file → Normal file
View File

0
F1/DMA_GPIO/dma_gpio.bin Executable file → Normal file
View File

0
F1/GPIO_TIM/tim_gpio.bin Executable file → Normal file
View File

0
F1/GPS+ultrasonic/timelapse.bin Executable file → Normal file
View File

0
F1/GPS/GPS.bin Executable file → Normal file
View File

0
F1/Jeep_generator/jeep_generator.bin Executable file → Normal file
View File

0
F1/Timelapse_keyboard/timelapse.bin Executable file → Normal file
View File

0
F1/Timelapse_keyboard_only_lasers/timelapse.bin Executable file → Normal file
View File

0
F1/USBCDC_template/usb_cdc_simple.bin Executable file → Normal file
View File

0
F1/canon_lens/canon_lens.bin Executable file → Normal file
View File

0
F1/distance_meters/ultrasonic.bin Executable file → Normal file
View File

0
F1/hid_mouse_keyboard/usbhid.bin Executable file → Normal file
View File

0
F1/keyboard_snippet/keyboard.bin Executable file → Normal file
View File

0
F1/matrix_keyboard/matrkeyb.bin Executable file → Normal file
View File

0
F1/nokia5110/nokia5110.bin Executable file → Normal file
View File

0
F1/simple_cdc/usb_cdc_simple.bin Executable file → Normal file
View File

0
F1/stepper_motion/usb_cdc_simple.bin Executable file → Normal file
View File

0
F1/ultrasonic/ultrasonic.bin Executable file → Normal file
View File

0
F303-nolib/blink/blink.bin Executable file → Normal file
View File

0
F303-nolib/usart1/usart1.bin Executable file → Normal file
View File

0
F303-nolib/usarts/usart.bin Executable file → Normal file
View File