RISC-V/V203F6P6/thermometer/GsmDecoder.cpp
2025-01-31 16:38:37 +01:00

44 lines
1.7 KiB
C++

#include "pwmclass.h"
#include "GsmDecoder.h"
GsmDecoder::GsmDecoder(FIFO<uint32_t, FIFOLEN> & f) noexcept :
OneWay<uint16_t>(), fifo(f), enable(GPIOB, 1u), flash(), gsm(), idle(0u) {
}
static constexpr int INPUT_BIT_RANGE = 16;
static constexpr unsigned SIGMA_MASK = (1u << (INPUT_BIT_RANGE + 0)) - 1u;
static constexpr unsigned SIGNED_OFFEST = (1u << (INPUT_BIT_RANGE - 1));
// Předpokládá se na vstupu signed int o šířce INPUT_BIT_RANGE
// přičemž 0 na vstupu odpovídá MAXPWM / 2 na výstupu. Vypadá to divně, ale funguje.
static unsigned pwm_sd (const int input) {
static unsigned sigma = 0; // podstatné je, že proměnná je statická
const unsigned sample = (input + SIGNED_OFFEST) * MAXPWM;
sigma &= SIGMA_MASK; // v podstatě se odečte hodnota PWM
sigma += sample; // integrace prostým součtem
return sigma >> INPUT_BIT_RANGE;
}
unsigned GsmDecoder::Send(uint16_t * dptr, const unsigned len) {
uint32_t source;
if (fifo.Read(source)) {
enable << true; // zapni budič
idle = 0u;
gsm_frame tmp;
flash.ReadBlock(source, tmp, sizeof(gsm_frame));
gsm.decode(tmp, tmpbuf);
for (unsigned n=0u, k=0u; k<len; n++) {
const int16_t s = tmpbuf[n];
dptr [k++] = pwm_sd (s); // vyzkoušená metoda jak vylepšit PWM
dptr [k++] = pwm_sd (s); // pokud máme frekvenci PWM větší
dptr [k++] = pwm_sd (s); // než vzorkovací frekvence signálu ft = n * fs, n = 3
}
return GSMLEN;
}
idle += 1u;
if (idle > 3u) { // pro vypnutí budiče je lépe chvilinku počkat
idle = 3u;
enable << false;
}
for (unsigned n=0u; n<len; n++) {
dptr [n] = MAXPWM >> 1;
}
return 0;
}