Some modifications of RGB LED panel

This commit is contained in:
Edward Emelianov 2021-04-20 20:17:58 +03:00
parent 59fe90b9e0
commit 1335cae775
16 changed files with 300 additions and 28 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

@ -0,0 +1,71 @@
/*
* This file is part of the LED_screen 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/>.
*/
// random numbers generator based on ADC values of Tsens and Vref
#include "adcrandom.h"
#define ADC_CHANNELS_NO (2)
// 16-Tsens, 17-Vref
static uint8_t const ADCchno[ADC_CHANNELS_NO] = {16, 17};
uint16_t getADCval(uint8_t ch){
if(ch >= ADC_CHANNELS_NO) return 0;
ADC1->SQR3 = ADCchno[ch];
ADC1->SR = 0;
// turn ON ADC
ADC1->CR2 |= ADC_CR2_ADON;
while(!(ADC1->SR & ADC_SR_EOC)); // wait end of conversion
return ADC1->DR;
}
uint32_t getRand(){
uint32_t r = 0;
for(int i = 0; i < 16; ++i){
r <<= 1;
r |= (getADCval(0) & 1);
r <<= 1;
r |= (getADCval(1) & 1);
}
r ^= r << 13;
r ^= r >> 17;
r ^= r << 5;
return r;
}
void adc_setup(){
//GPIOC->CRL |= CRL(0, CNF_ANALOG|MODE_INPUT);
uint32_t ctr = 0;
// Enable clocking
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
RCC->CFGR &= ~(RCC_CFGR_ADCPRE);
RCC->CFGR |= RCC_CFGR_ADCPRE_DIV2; // ADC clock = RCC / 2
// sampling time - 1.5 cycles for all chanels
//ADC1->SMPR1 = ADC_SMPR1_SMP10_0 | ADC_SMPR1_SMP16_0 | ADC_SMPR1_SMP17_0;//channels 10, 16 and 17
// single mode, enable vref & Tsens; wake up ADC
ADC1->CR2 |= ADC_CR2_TSVREFE | ADC_CR2_ADON;
// wait for Tstab - at least 1us
while(++ctr < 0xff) nop();
// calibration
ADC1->CR2 |= ADC_CR2_RSTCAL;
ctr = 0; while((ADC1->CR2 & ADC_CR2_RSTCAL) && ++ctr < 0xfffff);
ADC1->CR2 |= ADC_CR2_CAL;
ctr = 0; while((ADC1->CR2 & ADC_CR2_CAL) && ++ctr < 0xfffff);
}

View File

@ -0,0 +1,29 @@
/*
* This file is part of the LED_screen 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 ADCRANDOM_H__
#define ADCRANDOM_H__
#include <stm32f1.h>
void adc_setup();
uint16_t getADCval(uint8_t ch);
uint32_t getRand();
#endif // ADCRANDOM_H__

View File

@ -0,0 +1,108 @@
/*
* This file is part of the LED_screen 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 "balls.h"
#include "screen.h"
#include "proto.h"
#include "usb.h"
extern uint32_t volatile Tms;
// fraction of 1 for fixed point
#define FIXPOINT (10000)
// max pause in ms to add next ball
#define MAXPAUSEADDBALL (5000)
// max speed in fractions per millisecond
#define SPEEDMAX (300)
// max balls amount
#define NBALLSMAX (20)
// coordinates/speeds in fractions
static int
x[NBALLSMAX], y[NBALLSMAX],
xnew[NBALLSMAX], ynew[NBALLSMAX],
xspeed[NBALLSMAX], yspeed[NBALLSMAX];
static uint8_t colr[NBALLSMAX];
static int Nballs = 0;
static uint32_t Tlast, Taddb;
static void clear_balls(){
for(int i = 0; i < Nballs; ++i)
DrawPix(x[i]/FIXPOINT, y[i]/FIXPOINT, 0);
}
static void draw_balls(){
for(int i = 0; i < Nballs; ++i){
x[i] = xnew[i]; y[i] = ynew[i];
DrawPix(x[i]/FIXPOINT, y[i]/FIXPOINT, colr[i]);
}
}
static void add_ball(){
if(Nballs == NBALLSMAX) return;
uint8_t c = getRand() & 0xff;
if(c == 0) c = 1;
colr[Nballs] = c;
x[Nballs] = SCREEN_WIDTH*FIXPOINT/2;
y[Nballs] = SCREEN_HEIGHT*FIXPOINT/2;
xspeed[Nballs] = ((int)getRand()) % SPEEDMAX;
yspeed[Nballs] = ((int)getRand()) % SPEEDMAX;
++Nballs;
Taddb = Tms + getRand() % MAXPAUSEADDBALL;
}
void balls_init(){
Nballs = 0;
setBGcolor(0);
ClearScreen();
ScreenON();
Tlast = Tms;
add_ball();
}
//#define abs(x) ((x<0) ? -x : x)
void process_balls(){
if(Tms == Tlast) return;
if(Nballs < NBALLSMAX && Taddb < Tms){
add_ball();
}
int diff = (int)(Tms - Tlast);
for(int i = 0; i < Nballs; ++i){
xnew[i] = x[i] + xspeed[i]*diff;
ynew[i] = y[i] + yspeed[i]*diff;
inline void xrev(){xspeed[i] = -xspeed[i]; xnew[i] = x[i] + xspeed[i]*diff;}
inline void yrev(){yspeed[i] = -yspeed[i]; ynew[i] = y[i] + yspeed[i]*diff;}
if(xnew[i] < 0) xrev();
else if(xnew[i] > SCREEN_WIDTH*FIXPOINT) xrev();
if(ynew[i] < 0) yrev();
else if(ynew[i] > SCREEN_HEIGHT*FIXPOINT) yrev();
int nx = xnew[i]/FIXPOINT, ny = ynew[i]/FIXPOINT;
int dx = nx - x[i]/FIXPOINT, dy = ny - y[i]/FIXPOINT;
if((dx || dy) && GetPix(nx, ny)){ // change direction in case of collisions
xrev(); yrev();
xspeed[i] += getRand() & 3; // and randomly change speed
yspeed[i] += getRand() & 3;
}
}
clear_balls();
draw_balls();
Tlast = Tms;
}

View File

@ -0,0 +1,26 @@
/*
* This file is part of the LED_screen 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 BALLS_H__
#define BALLS_H__
void process_balls();
void balls_init();
#endif // BALLS_H__

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB

View File

@ -1230,7 +1230,7 @@ const uint8_t font14_table[SYMBOLS_AMOUNT *(FONT14BYTES+1)] = {
________,________ ________,________
// 0x5F // 0x5F
, ,
9, 8,
________,________, ________,________,
________,________, ________,________,
________,________, ________,________,

View File

@ -1226,7 +1226,7 @@ const uint8_t font16_table[SYMBOLS_AMOUNT *(FONT16BYTES+1)] = {
________,________ ________,________
// 0x5F // 0x5F
, ,
9, 8,
________,________, ________,________,
________,________, ________,________,
________,________, ________,________,

View File

@ -0,0 +1,7 @@
#!/bin/bash
COMDEV=/dev/ttyUSB0
stty -F $COMDEV -hupcl -opost -onlcr -isig -iexten -echo -echoe -echok -echoctl -echoke -icanon min 0 time 1 115200
echo "G" > $COMDEV &
cat $COMDEV

View File

@ -77,7 +77,7 @@ static inline void tim_setup(){
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
// PCS=1 don't work; // PCS=1 don't work;
TIM3->PSC = 9; // 7.2MHz TIM3->PSC = 9; // 7.2MHz
TIM3->ARR = 7; // 900kHz TIM3->ARR = 7;
TIM3->CCMR1 = TIM_CCMR1_OC1M; // PWM mode 2 (inactive->active) TIM3->CCMR1 = TIM_CCMR1_OC1M; // PWM mode 2 (inactive->active)
//TIM3->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1; // PWM mode 1 (active->inactive) //TIM3->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1; // PWM mode 1 (active->inactive)
TIM3->CCER = TIM_CCER_CC1E; // output 1 enable TIM3->CCER = TIM_CCER_CC1E; // output 1 enable
@ -100,19 +100,6 @@ void stopTIMDMA(){
TIM3->CR1 = 0; // turn off timer TIM3->CR1 = 0; // turn off timer
} }
/*
static inline uint8_t getcolrvals(uint8_t colr, uint8_t Ntick){
uint8_t *rgb = pack2RGB(colr);
uint8_t result = 0; // bits: 0-R, 1-G, 2-B
for(int i = 0; i < 3; ++i){
#ifdef SCREEN_IS_NEGATIVE
if(rgb[i] < Ntick) result |= 1 << i;
#else
if(rgb[i] >= Ntick) result |= 1 << i;
#endif
}
return result;
}*/
static inline uint8_t getcolrvals(uint8_t colr, uint8_t Ntick){ static inline uint8_t getcolrvals(uint8_t colr, uint8_t Ntick){
uint8_t result = 0; // bits: 0-R, 1-G, 2-B uint8_t result = 0; // bits: 0-R, 1-G, 2-B
#ifdef SCREEN_IS_NEGATIVE #ifdef SCREEN_IS_NEGATIVE
@ -161,7 +148,7 @@ void TIM_DMA_transfer(uint8_t blknum){
TIM3->CR1 = 0; // turn off timer TIM3->CR1 = 0; // turn off timer
transfer_done = 0; transfer_done = 0;
// set first pixel color // set first pixel color
COLR_port->BSRR = dmabuf[0]; //COLR_port->BSRR = dmabuf[0];
DMA1_Channel3->CNDTR = SCREEN_WIDTH; DMA1_Channel3->CNDTR = SCREEN_WIDTH;
DMA1_Channel3->CCR |= DMA_CCR_EN; // start DMA DMA1_Channel3->CCR |= DMA_CCR_EN; // start DMA
TIM3->CCR1 = 4; // 50% PWM TIM3->CCR1 = 4; // 50% PWM
@ -171,11 +158,11 @@ void TIM_DMA_transfer(uint8_t blknum){
// DMA transfer complete - stop transfer // DMA transfer complete - stop transfer
void dma1_channel3_isr(){ void dma1_channel3_isr(){
TIM3->SR = 0; //TIM3->CR1 |= TIM_CR1_OPM; // set one pulse mode to turn off timer after last CLK pulse
TIM3->CR1 |= TIM_CR1_OPM; // set one pulse mode to turn off timer after last CLK pulse //TIM3->SR = 0;
TIM3->CR1 = 0;
DMA1_Channel3->CCR &= ~DMA_CCR_EN; // stop DMA DMA1_Channel3->CCR &= ~DMA_CCR_EN; // stop DMA
while(!(TIM3->SR & TIM_SR_UIF)); // wait for last pulse //while(!(TIM3->SR & TIM_SR_UIF)); // wait for last pulse
//while(TIM3->CNT < 7);
SCRN_DISBL(); // clear main output SCRN_DISBL(); // clear main output
ADDR_port->ODR = (ADDR_port->ODR & ~(ADDR_pin)) | (blknum_curr << ADDR_roll); // set address ADDR_port->ODR = (ADDR_port->ODR & ~(ADDR_pin)) | (blknum_curr << ADDR_roll); // set address
SET(LAT); // activate latch SET(LAT); // activate latch
@ -183,6 +170,7 @@ void dma1_channel3_isr(){
transfer_done = 1; transfer_done = 1;
CLEAR(LAT); CLEAR(LAT);
SCRN_ENBL(); // activate main output SCRN_ENBL(); // activate main output
process_screen();
//USB_send("transfer done\n"); //USB_send("transfer done\n");
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View File

@ -19,6 +19,8 @@
* MA 02110-1301, USA. * MA 02110-1301, USA.
*/ */
#include "adcrandom.h"
#include "balls.h"
#include "fonts.h" #include "fonts.h"
#include "hardware.h" #include "hardware.h"
#include "proto.h" #include "proto.h"
@ -27,7 +29,7 @@
#include "usb_lib.h" #include "usb_lib.h"
volatile uint32_t Tms = 0; volatile uint32_t Tms = 0;
uint8_t countms = 0, rainbow = 0; uint8_t countms = 0, rainbow = 0, balls = 0;
/* Called when systick fires */ /* Called when systick fires */
void sys_tick_handler(void){ void sys_tick_handler(void){
@ -74,6 +76,7 @@ int main(void){
hw_setup(); hw_setup();
USBPU_OFF(); USBPU_OFF();
adc_setup();
USB_setup(); USB_setup();
PutStringAt(1, SCREEN_HEIGHT-1-curfont->baseline, "Test string"); PutStringAt(1, SCREEN_HEIGHT-1-curfont->baseline, "Test string");
iwdg_setup(); iwdg_setup();
@ -105,8 +108,9 @@ int main(void){
lastR = Tms; lastR = Tms;
nxtrainbow(); nxtrainbow();
} }
if(balls) process_balls();
IWDG->KR = IWDG_REFRESH; IWDG->KR = IWDG_REFRESH;
process_screen(); //process_screen();
usb_proc(); usb_proc();
char *txt; const char *ans; char *txt; const char *ans;
if((txt = get_USB())){ if((txt = get_USB())){

View File

@ -16,12 +16,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "adcrandom.h"
#include "balls.h"
#include "fonts.h" #include "fonts.h"
#include "proto.h" #include "proto.h"
#include "screen.h" #include "screen.h"
#include "usb.h" #include "usb.h"
extern uint8_t countms, rainbow; extern uint8_t countms, rainbow, balls;
extern uint32_t Tms;
char *omit_spaces(const char *buf){ char *omit_spaces(const char *buf){
while(*buf){ while(*buf){
@ -156,9 +159,12 @@ char *getnum(const char *txt, uint32_t *N){
const char* helpmsg = const char* helpmsg =
"'0/1' - screen off/on\n" "'0/1' - screen off/on\n"
"'2,3' - select font\n" "'2,3' - select font\n"
"'A' - get ADC values\n"
"'B' - start/stop rainBow\n" "'B' - start/stop rainBow\n"
"'b' - start/stop Balls\n"
"'C' - clear screen with given color\n" "'C' - clear screen with given color\n"
"'F' - set foreground color\n" "'F' - set foreground color\n"
"'G' - get 100 random numbers\n"
"'f' - get FPS\n" "'f' - get FPS\n"
"'R' - software reset\n" "'R' - software reset\n"
"'W' - test watchdog\n" "'W' - test watchdog\n"
@ -186,6 +192,13 @@ const char *parse_cmd(const char *buf){
if(choose_font(FONT16)) return "Font16\n"; if(choose_font(FONT16)) return "Font16\n";
return "err\n"; return "err\n";
break; 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': case 'B':
if(rainbow){ if(rainbow){
rainbow = 0; rainbow = 0;
@ -195,12 +208,32 @@ const char *parse_cmd(const char *buf){
return "Start rainbow\n"; return "Start rainbow\n";
} }
break; break;
case 'b':
if(balls){
balls = 0;
return "Stop balls\n";
}else{
balls_init();
balls = 1;
return "Start balls\n";
}
case 'f': case 'f':
if(SCREEN_RELAX == getScreenState()) return "Screen is inactive\n"; if(SCREEN_RELAX == getScreenState()) return "Screen is inactive\n";
USB_send("FPS="); USB_send("FPS=");
USB_send(u2str(getFPS())); USB_send(u2str(getFPS()));
USB_send("\n"); USB_send("\n");
return NULL; 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': case 'R':
USB_send("Soft reset\n"); USB_send("Soft reset\n");
NVIC_SystemReset(); NVIC_SystemReset();

View File

@ -82,6 +82,10 @@ void XORPix(int16_t X, int16_t Y, uint8_t pix){
if(X < 0 || X > SCREEN_WIDTH-1 || Y < 0 || Y > SCREEN_HEIGHT-1) return; // outside of screen if(X < 0 || X > SCREEN_WIDTH-1 || Y < 0 || Y > SCREEN_HEIGHT-1) return; // outside of screen
screenbuf[Y*SCREEN_WIDTH + X] ^= pix; screenbuf[Y*SCREEN_WIDTH + X] ^= pix;
} }
uint8_t GetPix(int16_t X, int16_t Y){
if(X < 0 || X > SCREEN_WIDTH-1 || Y < 0 || Y > SCREEN_HEIGHT-1) return 0;
return screenbuf[Y*SCREEN_WIDTH + X];
}
/** /**
* @brief DrawCharAt - draws character @ position X,Y (this point is left baseline corner of char!) * @brief DrawCharAt - draws character @ position X,Y (this point is left baseline corner of char!)
@ -147,10 +151,10 @@ void process_screen(){
ConvertScreenBuf(screenbuf, currentB, Ntick); // convert data ConvertScreenBuf(screenbuf, currentB, Ntick); // convert data
TIM_DMA_transfer(currentB); // start transfer TIM_DMA_transfer(currentB); // start transfer
ScrnState = SCREEN_ACTIVE; ScrnState = SCREEN_ACTIVE;
if(++currentB >= NBLOCKS){ if(++Ntick >= 7){
currentB = 0; // start again Ntick = 0;
if(++Ntick >= 7){ if(++currentB >= NBLOCKS){
Ntick = 0; currentB = 0; // start again
++framecnt; ++framecnt;
if(Tms - Tfps > 999){ if(Tms - Tfps > 999){
FPS = framecnt; FPS = framecnt;
@ -171,6 +175,7 @@ void process_screen(){
void ScreenON(){ void ScreenON(){
ScrnState = SCREEN_UPDATENXT; ScrnState = SCREEN_UPDATENXT;
Tfps = Tms; Tfps = Tms;
process_screen();
} }
void ScreenOFF(){ void ScreenOFF(){

View File

@ -48,6 +48,7 @@ void setFGcolor(uint8_t c);
void DrawPix(int16_t X, int16_t Y, uint8_t pix); void DrawPix(int16_t X, int16_t Y, uint8_t pix);
void InvertPix(int16_t X, int16_t Y); void InvertPix(int16_t X, int16_t Y);
void XORPix(int16_t X, int16_t Y, uint8_t pix); void XORPix(int16_t X, int16_t Y, uint8_t pix);
uint8_t GetPix(int16_t X, int16_t Y);
uint8_t DrawCharAt(int16_t X, int16_t Y, uint8_t Char); uint8_t DrawCharAt(int16_t X, int16_t Y, uint8_t Char);
uint8_t PutStringAt(int16_t X, int16_t Y, const char *str); uint8_t PutStringAt(int16_t X, int16_t Y, const char *str);
uint8_t *getScreenBuf(); uint8_t *getScreenBuf();