gsm -> voltmetr

This commit is contained in:
Kizarm 2024-05-12 16:53:28 +02:00
parent 153ccf570b
commit b1d64e1ab3
5 changed files with 227 additions and 8 deletions

View file

@ -18,7 +18,7 @@ DEL = rm -f
# zdrojaky
OBJS = main.o pwmclass.o
OBJS += player.o GsmDecoder.o gsmdata.o wrap.o
OBJS += player.o GsmDecoder.o gsmdata.o wrap.o adcdma.o
include $(TARGET)/$(TOOL).mk
BOBJS = $(addprefix $(BLD),$(OBJS))

114
V203/gsm/adcdma.cpp Normal file
View file

@ -0,0 +1,114 @@
#include "system.h"
#include "oneway.h"
#include "adcdma.h"
static AdcDma * pInstance = nullptr;
extern "C" void DMA1_Channel1_IRQHandler( void ) __attribute__((interrupt));
void DMA1_Channel1_IRQHandler( void ) {
DMA1_Type::INTFR_DEF state (DMA1.INTFR);
DMA1.INTFCR.R = state.R; // clear all
if (!pInstance) return;
if (state.B.HTIF1 != RESET) pInstance->send (false);
else if (state.B.TCIF1 != RESET) pInstance->send (true);
}
static inline void EnableClock (void) noexcept {
// Enable DMA
RCC.AHBPCENR.modify([](RCC_Type::AHBPCENR_DEF & r) -> auto {
r.B.SRAMEN = SET;
r.B.DMA1EN = SET;
return r.R;
});
// Enable ADC + GPIOA
RCC.APB2PCENR.modify([](RCC_Type::APB2PCENR_DEF & r) -> auto {
r.B.ADC1EN = SET;
r.B.IOPAEN = SET;
return r.R;
});
RCC.APB1PCENR.B.TIM3EN = SET; // Enable TIM3
RCC.CFGR0.B.ADCPRE = 3u; // 11: PCLK2 divided by 8 // max 14 MHz (18) ?
// PIN PA2 / A2
GPIOA.CFGLR.modify([](GPIOA_Type::CFGLR_DEF & r) -> auto {
r.B.MODE2 = 0u;
r.B.CNF2 = 0u;
return r.R;
});
}
static inline void TimerInit (uint32_t us) noexcept {
TIM3.PSC.R = 143u; // 1 MHz Fs
TIM3.ATRLR.R = us - 1u;
// TRGO update for ADC
TIM3.CTLR2.B.MMS = 2u;
}
static inline void AdcCalibrate (void) noexcept {
// RESET
RCC.APB2PRSTR.B.ADC1RST = SET;
RCC.APB2PRSTR.B.ADC1RST = RESET;
// set channels
ADC1.RSQR3__CHANNEL.B.SQ1__CHSEL = 2u; // CH2
ADC1.SAMPTR2_CHARGE2.B.SMP2_TKCG2 = 7u;
/*
ADC1.RSQR3__CHANNEL.B.SQ1__CHSEL = 16u; // teplota
ADC1.SAMPTR1_CHARGE1.B.SMP16_TKCG16 = 7u;
*/
ADC1.RSQR1.B.L = 0u; // 1 regular conversion
ADC1.CTLR1.B.SCAN = SET;
ADC1.CTLR2.B.ADON = SET;
//ADC1.CTLR2.B.TSVREFE = SET;
ADC1.CTLR2.B.RSTCAL = SET; // Launch the calibration by setting RSTCAL
while (ADC1.CTLR2.B.RSTCAL != RESET); // Wait until RSTCAL=0
ADC1.CTLR2.B.CAL = SET; // Launch the calibration by setting CAL
while (ADC1.CTLR2.B.CAL != RESET); // Wait until CAL=0
}
typedef __SIZE_TYPE__ size_t;
static inline void Dma1Ch1Init (void * ptr) noexcept {
// Configure the peripheral data register address
DMA1.PADDR1.R = reinterpret_cast<size_t> (& ADC1.RDATAR_DR_ACT_DCG);
// Configure the memory address
DMA1.MADDR1.R = reinterpret_cast<size_t> (ptr);
// Configure the number of DMA tranfer to be performs on DMA channel 1
DMA1.CNTR1 .R = AFULL_LEN;
// Configure increment, size, interrupts and circular mode
DMA1.CFGR1.modify([] (DMA1_Type::CFGR1_DEF & r) -> auto {
r.B.PL = 3u; // highest priority
r.B.MEM2MEM = RESET; // periferal -> memory
r.B.MINC = SET; // memory increment
r.B.MSIZE = 1u; // 16-bit
r.B.PSIZE = 1u; // 16-bit
r.B.HTIE = SET; // INT Enable HALF
r.B.TCIE = SET; // INT Enable FULL
r.B.CIRC = SET; // Circular MODE
// Enable DMA Channel 1
r.B.EN = SET;
return r.R;
});
}
static inline void AdcPostInit (void) noexcept {
ADC1.CTLR2.modify([](ADC1_Type::CTLR2_DEF & r) -> auto {
r.B.DMA = SET;
r.B.EXTTRIG = SET;
r.B.EXTSEL = 4u; // TRGO event of timer 3
r.B.SWSTART = SET;
return r.R;
});
}
////////////////////////////////////////////////////////////////////////////////////
AdcDma::AdcDma() noexcept : pL (buffer), pH (buffer + AHALF_LEN), dst (nullptr) {
pInstance = this;
EnableClock ();
TimerInit (1000u);
NVIC.EnableIRQ (DMA1_Channel1_IRQn);
AdcCalibrate();
Dma1Ch1Init (buffer);
AdcPostInit ();
// start timer
TIM3.CTLR1.B.CEN = SET;
}
inline void AdcDma::send(const bool b) {
if (!dst) return;
if (b) dst->Send (pH, AHALF_LEN);
else dst->Send (pL, AHALF_LEN);
}

21
V203/gsm/adcdma.h Normal file
View file

@ -0,0 +1,21 @@
#ifndef ADCDMA_H
#define ADCDMA_H
#include <stdint.h>
class OneWay;
static constexpr unsigned AHALF_LEN = 120u;
static constexpr unsigned AFULL_LEN = AHALF_LEN * 2u;
class AdcDma {
uint16_t * pL;
uint16_t * pH;
uint16_t buffer [AFULL_LEN];
OneWay * dst;
public:
explicit AdcDma () noexcept;
void attach (OneWay & d) { dst = & d; }
void send (const bool b);
};
#endif // ADCDMA_H

View file

@ -1259,7 +1259,8 @@ static const gsm_frame gsm_data_hafo[] = {
{0xd0,0x9b,0x9a,0xe1,0x5a,0x50,0x00,0x49,0x24,0x92,0x49,0x24,0x54,0x00,0x49,0x24,0x92,0x49,0x24,0x50,0x00,0x49,0x24,0x92,0x49,0x24,0x50,0x00,0x49,0x24,0x92,0x49,0x24,},
{0xd0,0x60,0xa2,0xe1,0x5a,0x50,0x00,0x49,0x24,0x92,0x49,0x24,0x50,0x00,0x49,0x24,0x92,0x49,0x24,0x50,0x00,0x49,0x24,0x92,0x49,0x24,0x50,0x00,0x49,0x24,0x8e,0x49,0x24,},
};
static const gsm_frame gsm_data_units[] = {
/*
static const gsm_frame gsm_data_units[] = { // stupňů celsia
{0xdb,0xe4,0xd2,0x14,0xd2,0x50,0x02,0x36,0xdb,0x69,0xa0,0xa2,0x52,0xc1,0x97,0x52,0x50,0x2a,0xa6,0x7a,0xa2,0x34,0x78,0x78,0x58,0x6c,0x6f,0x01,0xd9,0x28,0xbc,0xeb,0xdf,},
{0xda,0xa4,0xe3,0xaa,0x23,0x63,0x02,0x6c,0x6b,0xe7,0x09,0x53,0x97,0xa7,0x49,0x1b,0xa8,0xd5,0x18,0x53,0x29,0xce,0xa3,0x96,0x67,0x68,0x53,0x28,0xcd,0xcc,0x72,0x63,0x61,},
{0xd8,0xec,0xe4,0x71,0xe2,0x52,0x89,0x2f,0xd9,0x95,0xd3,0x86,0x91,0x6a,0x4b,0x15,0x6f,0xd5,0x98,0x98,0xeb,0x3b,0xad,0x71,0xbe,0xf1,0x7e,0xcb,0xcc,0xe2,0xf2,0x9d,0x99,},
@ -1325,6 +1326,35 @@ static const gsm_frame gsm_data_units[] = {
{0xd0,0x5e,0x7b,0xe1,0x9a,0xa6,0x00,0x47,0x24,0x92,0x49,0x24,0x50,0x00,0x49,0x24,0x92,0x49,0x24,0xb2,0x00,0x49,0x23,0x92,0x49,0x24,0x50,0x00,0x49,0x24,0x92,0x49,0x24,},
{0xd0,0xd9,0x92,0xa1,0x1a,0x50,0x00,0x49,0x24,0x92,0x49,0x24,0x50,0x00,0x49,0x24,0x92,0x49,0x24,0x50,0x00,0x49,0x24,0x92,0x49,0x24,0x54,0x00,0x49,0x24,0x92,0x49,0x24,},
};
*/
static const gsm_frame gsm_data_units[] = { // volt
{0xd2,0x55,0x62,0x58,0xda,0x50,0x00,0x59,0x77,0x9b,0xdd,0x33,0x70,0xa0,0xe7,0x1c,0xaa,0xb6,0xea,0x9c,0xc0,0xb8,0xd4,0x95,0x99,0x13,0xe2,0xc0,0xc4,0xe4,0x8c,0xc9,0x1b,},
{0xd2,0x21,0xbb,0x69,0x63,0xd5,0x00,0xb9,0x1d,0x52,0x47,0x56,0xcd,0xa1,0x37,0xaf,0x72,0xa8,0xd2,0x56,0xe1,0x49,0x2c,0xb5,0xa2,0x40,0x57,0xc2,0xa9,0x25,0xb2,0xc6,0x80,},
{0xd0,0xee,0xbb,0x21,0xeb,0x53,0x03,0xa9,0x27,0x6a,0xc8,0xaa,0x52,0xc2,0xcb,0xd9,0xa6,0xf8,0x78,0xa4,0xa4,0x17,0xdb,0x6a,0xd9,0x84,0x54,0xc4,0x97,0xd3,0x8a,0xc7,0x13,},
{0xd0,0xf1,0xc2,0xe1,0xeb,0xa6,0x84,0x44,0xba,0x75,0xc7,0x62,0x52,0x82,0x32,0x7b,0x4e,0xbb,0x5b,0xa2,0xe1,0x10,0xf9,0x5d,0xcc,0xd3,0xa4,0xc1,0x10,0xf2,0x5d,0xcd,0x51,},
{0xd3,0x98,0x8b,0x29,0xe3,0xa3,0xc4,0x26,0x96,0x93,0xdb,0xaa,0x53,0xa5,0x04,0x0d,0xca,0xe6,0xe1,0x53,0x04,0x18,0x44,0xee,0x7b,0x24,0xa7,0xf2,0x38,0xdc,0x8e,0x47,0x27,},
{0xd3,0x2a,0xba,0xdc,0xa3,0x50,0x14,0x08,0xdb,0x91,0xc9,0x24,0x54,0xcc,0xc6,0x40,0xad,0xd7,0x6f,0xee,0x70,0x46,0x80,0xf1,0x55,0x35,0x53,0x4f,0xc7,0x09,0x9c,0xd6,0xf5,},
{0xd3,0xed,0xb2,0x60,0x63,0x53,0x4d,0xc4,0xc8,0x3e,0x48,0x9e,0x53,0x8d,0xfb,0x0b,0x2f,0xba,0xe6,0x53,0xed,0xba,0x5b,0xd4,0xc8,0x67,0x53,0xce,0x9a,0xa4,0x8f,0x8c,0xad,},
{0xd4,0x2d,0xc2,0x20,0x9b,0x53,0xb1,0x1a,0xdb,0x36,0x0e,0x95,0xa3,0xb0,0x2f,0x23,0x30,0x4e,0x64,0x52,0xd0,0xd9,0x22,0x63,0xe2,0xe4,0x53,0x2f,0x35,0x62,0x65,0x76,0xab,},
{0xd3,0xf0,0xda,0x46,0xeb,0x51,0x4d,0x57,0xac,0x64,0x39,0x24,0xa0,0xcf,0x39,0xa5,0x48,0x49,0x25,0xa5,0x4d,0x97,0x65,0x4c,0xf3,0x23,0x53,0x0a,0x77,0x7a,0xa4,0x9e,0xa4,},
{0xd4,0x2a,0xdb,0xc2,0xab,0x53,0x89,0xda,0xb3,0x89,0xae,0xcd,0x53,0x2c,0x49,0x2d,0x85,0x0e,0xdc,0xa3,0x0c,0x48,0xe5,0xad,0x91,0x9b,0xa3,0xac,0x48,0xa3,0x92,0xc1,0x23,},
{0xd3,0x6d,0x9b,0x12,0x2c,0x53,0x4b,0x47,0x65,0x89,0x89,0x44,0xa5,0x69,0xc5,0x64,0x66,0x8e,0xc4,0xa5,0x4a,0xc6,0xed,0x51,0x95,0xdb,0x53,0xc8,0x47,0x63,0x8d,0xd3,0x84,},
{0xd3,0x2f,0x8a,0x9d,0xac,0x53,0x08,0xf8,0xdd,0xe7,0x20,0x7a,0xa3,0x47,0xc7,0x2d,0x91,0xb0,0x3d,0xa5,0x09,0x38,0xe5,0x96,0x28,0x1d,0xa5,0xa6,0x2a,0xd4,0x75,0x2a,0xb9,},
{0xd2,0xf0,0x8a,0x59,0x74,0x53,0xe9,0x56,0xdc,0x86,0x45,0xb9,0x53,0xe9,0x43,0x23,0x8a,0x29,0x68,0xa5,0x49,0x28,0x6c,0x92,0xb4,0xcf,0x53,0xe7,0x49,0x1b,0x94,0x48,0xb7,},
{0xd3,0x6b,0xc3,0x0a,0x2d,0xa5,0x0b,0x29,0x23,0x72,0xc8,0xd0,0x53,0x49,0x27,0x64,0x96,0xda,0xc0,0xa3,0xe8,0x32,0xad,0x50,0x7d,0x18,0x53,0xec,0xc5,0x24,0xae,0x33,0x1f,},
{0xd4,0xa4,0x93,0x99,0x99,0xa5,0x09,0x07,0x97,0xaa,0xd8,0x15,0xa6,0xa9,0x26,0xfd,0x6d,0xb9,0x36,0xa6,0x27,0xb0,0x54,0x72,0xc9,0x6d,0xaa,0x42,0x32,0x14,0x2e,0xdb,0xae,},
{0xd5,0x1c,0x7b,0xa9,0x98,0xac,0x01,0x7a,0x94,0xad,0x39,0x7c,0xb4,0x20,0xfc,0x8d,0xcd,0x19,0xfa,0xa2,0xe0,0xa7,0xca,0xd1,0xa9,0x5a,0xab,0x40,0xd3,0x0c,0x96,0x49,0x1a,},
{0xd7,0x9b,0x59,0xa5,0x5a,0xb8,0x80,0xb7,0x39,0x6d,0xc8,0xe6,0xe0,0xa0,0xad,0x39,0x66,0x37,0x1c,0xe2,0xa0,0xb6,0xe4,0x29,0x46,0x5b,0xaa,0x40,0x29,0xde,0x8e,0x46,0xec,},
{0xd8,0xdd,0x5a,0x50,0xd9,0xde,0x80,0xba,0xe5,0x59,0xb6,0xe3,0x58,0xe0,0x53,0x7a,0xa8,0xb4,0xe4,0x5a,0xe0,0x1b,0xd1,0x49,0x25,0x1a,0xaa,0x80,0xc6,0xa3,0x85,0xd7,0x1a,},
{0xd8,0x9d,0x59,0x91,0x12,0x76,0xa0,0x6a,0x92,0x8d,0x99,0x09,0x76,0xa0,0xba,0xb3,0x91,0xb9,0x63,0x62,0xa0,0x46,0xab,0xcd,0x47,0x01,0xc8,0xc0,0xd7,0x33,0x75,0xc4,0xdc,},
{0xd4,0xd6,0x50,0xdd,0x12,0x78,0xc0,0xa4,0xe5,0x2e,0x38,0xa4,0x94,0x80,0x34,0xa2,0x36,0x45,0x22,0xf0,0xc0,0x49,0x27,0x55,0xa6,0xec,0xe0,0xa0,0x58,0x86,0xb0,0xcc,0xe3,},
{0xd6,0xd9,0x49,0x19,0x51,0xd8,0xc0,0xc7,0x23,0x8e,0x22,0xe3,0x5e,0x80,0x25,0x6a,0x69,0xd9,0x93,0x8c,0xe0,0x56,0x7e,0x56,0xc8,0xd2,0x72,0x80,0x2f,0xce,0x6b,0x2f,0x63,},
{0xd7,0x62,0x83,0x65,0xe2,0xcf,0xad,0x49,0x2f,0x07,0x99,0x6c,0x62,0x26,0xdc,0xc5,0x6a,0xc9,0x5b,0x92,0x29,0x4b,0x19,0x31,0xe9,0x10,0xee,0x24,0x05,0x1b,0xc5,0x42,0x8b,},
{0xd8,0xde,0x52,0x04,0x98,0xae,0x20,0xe6,0x53,0x75,0x25,0x76,0xe2,0x41,0x4d,0x63,0x4f,0xdc,0xdd,0xec,0x41,0x57,0x2d,0x96,0xd6,0xdf,0xc9,0x41,0xe9,0x24,0x71,0x29,0x8f,},
{0xd8,0xe4,0xf2,0x10,0xd9,0x5a,0x20,0xa3,0x4b,0x49,0xc7,0x23,0x74,0x20,0x48,0xd4,0x4e,0x38,0xdb,0xa0,0x20,0x38,0xe3,0x6d,0xb6,0xdb,0xf0,0x20,0x38,0xe3,0x6d,0xb6,0xdb,},
{0xd0,0x9b,0x9a,0xe1,0x5a,0x80,0x00,0x36,0xdb,0x92,0x49,0x24,0x50,0x00,0x49,0x24,0x92,0x49,0x24,0x50,0x00,0x49,0x24,0x92,0x49,0x24,0x50,0x00,0x49,0x24,0x92,0x49,0x24,},
{0xd0,0x9b,0x6b,0x65,0x9a,0x54,0x00,0x49,0x24,0x92,0x49,0x24,0x50,0x00,0x49,0x24,0x92,0x49,0x24,0x50,0x00,0x49,0x24,0x92,0x49,0x24,0x50,0x00,0x49,0x24,0x92,0x49,0x24,},
};
const SayedTexts sayed_texts = {
.nula = { gsm_data_nula, 22 },
.jedna = { gsm_data_jedna, 25 },
@ -1364,5 +1394,6 @@ const SayedTexts sayed_texts = {
.minus = { gsm_data_minus, 29 },
.point = { gsm_data_point, 29 },
.hafo = { gsm_data_hafo, 26 },
.units = { gsm_data_units, 64 },
//.units = { gsm_data_units, 64 },
.units = { gsm_data_units, 26 },
};

View file

@ -2,24 +2,77 @@
#include "fifo.h"
#include "player.h"
#include "GsmDecoder.h"
#include "adcdma.h"
#include "oneway.h"
#include "gpio.h"
////////////////////////////////////////////////////////
/* Demo, které jen počítá od 0 do 1000000. Výstup je PWM
* na pinech PA1/PA8 24kHz. Odvozeno a teploměru na
* na pinech PA1/PA8 24kHz. Odvozeno z teploměru na
* https://github.com/Kizarm/TTSCP_Client/tree/main/kecal/stm
*
* Tohle se do CH32V003 prostě nevejde.
* 12.05.2024 předěláno na voltmetr. Algoritmus měření není
* moc dokonalý, ale funguje to. Pin ADC je PA2, tlačítko
* na PA1 proti 3.3V. Teploměr na čipu stojí za prd, muselo
* by se to individuálně kalibrovat (nehledě na oteplení čipu).
*/
////////////////////////////////////////////////////////
class Meassure : public OneWay {
GpioClass buton;
FIFO<unsigned, 8u> fifo;
unsigned avg, old;
unsigned passcnt;
public:
explicit Meassure () noexcept : OneWay(),
buton (GPIOA,1,(GPIO_Speed_In | GPIO_UPDI_MPPO)),
fifo(), avg(0u), old(0u), passcnt(0u) {
buton.setPuPd(GPIO_PuPd_DOWN);
}
unsigned int Send (uint16_t * const ptr, const unsigned int len) override;
void out ();
};
static inline unsigned absdiff (const unsigned a, const unsigned b) {
int d = a - b;
return d < 0 ? -d : +d;
}
////////////////////////////////////////////////////////
static PwmClass pwm;
static FIFO<PText, FIFOLEN> fifo;
static TextPlayer player (fifo);
static GsmDecoder decoder(fifo);
static AdcDma adc;
static Meassure meas;
int main () {
pwm.attach(decoder);
int pass = 0u;
pwm.attach (decoder);
adc.attach (meas);
for (;;) {
player.say(pass++);
pwm.delay ();
meas.out();
}
return 0;
}
////////////////////////////////////////////////////////
static constexpr unsigned BK = 3316u << 4; // Mělo by to být přesně 3300.
unsigned int Meassure::Send(uint16_t * const ptr, const unsigned int len) {
for (unsigned n=0; n<len; n++) {
const unsigned mv = (BK * ptr [n]) >> 16;
avg = (avg * 15 + mv) >> 4; // klouzavý průměr s postupným zapomínáním
}
fifo.Write (avg);
return 0;
}
void Meassure::out() {
unsigned t;
if (fifo.Read (t)) {
if (passcnt) { passcnt -= 1u; } else {
const unsigned delta = absdiff(t, old);
if (delta > 10 or buton) {
old = t;
player.say(old, 3);
player.say(sayed_texts.units);
passcnt = 10u;
}
}
}
}