2024-10-21 10:26:41 +02:00
|
|
|
#include "samplering.h"
|
|
|
|
|
|
|
|
static const char * const hexstr = "0123456789ABCDEF";
|
|
|
|
|
|
|
|
uint32_t SampleRing::Up (const char * data, const uint32_t len) {
|
|
|
|
for (unsigned n=0; n<len; n++) {
|
|
|
|
const char c = data [n];
|
|
|
|
switch (c) {
|
2024-10-26 12:22:17 +02:00
|
|
|
case '?':
|
|
|
|
rcvd_counter = 0;
|
|
|
|
SendSettings();
|
|
|
|
break;
|
2024-10-21 10:26:41 +02:00
|
|
|
case '$':
|
|
|
|
rcvd_counter = 0;
|
|
|
|
rcvd_status = RCVD_DATA;
|
|
|
|
break;
|
|
|
|
case '\r':
|
|
|
|
case '\n':
|
|
|
|
CmdReceived ();
|
|
|
|
rcvd_counter = 0;
|
|
|
|
rcvd_status = RCVD_IDLE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (rcvd_status == RCVD_DATA) {
|
|
|
|
rcvd_buffer [rcvd_counter] = c;
|
|
|
|
rcvd_counter += 1u;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
void SampleRing::CmdReceived() {
|
|
|
|
if (rcvd_counter == 0u) return;
|
|
|
|
unsigned result = 0u;
|
|
|
|
for (unsigned n=0; n<rcvd_counter; n++) {
|
|
|
|
const char c = rcvd_buffer [n];
|
|
|
|
result *= 16;
|
|
|
|
if ((c >= '0') and (c <= '9')) {
|
|
|
|
result += (unsigned) (c - '0');
|
|
|
|
} else if ((c >= 'A') and (c <= 'F')) {
|
|
|
|
result += (unsigned) (c - 'A' + 10);
|
|
|
|
} else if ((c >= 'a') and (c <= 'f')) {
|
|
|
|
result += (unsigned) (c - 'a' + 10);
|
|
|
|
} else {
|
|
|
|
// chyba : nech byt
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CommandPass (result);
|
|
|
|
}
|
2024-10-26 12:22:17 +02:00
|
|
|
/* in adcscope.cpp
|
|
|
|
void SampleRing::ReloadTimer(const unsigned int n) {
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
void SampleRing::SendSettings() {
|
|
|
|
const unsigned max = 64;
|
|
|
|
char buf [max];
|
|
|
|
unsigned idx = 0;
|
2024-11-08 20:56:19 +01:00
|
|
|
AllSettings as (m_settings, m_time_base_order, voltage);
|
2024-10-26 12:22:17 +02:00
|
|
|
buf [idx++] = '!';
|
|
|
|
for (unsigned n=0u; n<sizeof(as); n++) {
|
|
|
|
const uint8_t c = as.common[n];
|
|
|
|
buf [idx++] = hexstr [c >> 4];
|
|
|
|
buf [idx++] = hexstr [c & 0xF];
|
|
|
|
}
|
|
|
|
buf [idx++] = '\r';
|
|
|
|
buf [idx++] = '\n';
|
|
|
|
buf [idx] = '\0';
|
|
|
|
BlockSend (buf, idx);
|
|
|
|
}
|
|
|
|
|
2024-10-21 10:26:41 +02:00
|
|
|
void SampleRing::CommandPass(const unsigned int cmd) {
|
|
|
|
RcvdHeader header;
|
|
|
|
header.common = cmd & 0xFFFF;
|
|
|
|
const DESTINATION dest = static_cast<DESTINATION> (header.bits.destinat);
|
|
|
|
switch (dest) {
|
|
|
|
case DEST_CHA:
|
2024-11-08 20:56:19 +01:00
|
|
|
voltage.a = header.bits.cmd_value;
|
|
|
|
spi.send (voltage.common, 1);
|
|
|
|
break;
|
2024-10-21 10:26:41 +02:00
|
|
|
case DEST_CHB:
|
2024-11-08 20:56:19 +01:00
|
|
|
voltage.b = header.bits.cmd_value;
|
|
|
|
spi.send (voltage.common, 1);
|
2024-10-21 10:26:41 +02:00
|
|
|
break;
|
|
|
|
case DEST_BASE:
|
2024-10-26 12:22:17 +02:00
|
|
|
m_time_base_order = header.bits.cmd_value;
|
|
|
|
ReloadTimer (m_time_base_order);
|
2024-10-21 10:26:41 +02:00
|
|
|
break;
|
|
|
|
case DEST_TRIG: {
|
|
|
|
const TRIGGER_CMD command = static_cast<TRIGGER_CMD> (header.bits.cmd_type);
|
|
|
|
switch (command) {
|
|
|
|
case TRIGGER_CMD_OFSET: m_settings.offset = header.bits.cmd_value; break;
|
|
|
|
case TRIGGER_CMD_VALUE: m_settings.value = header.bits.cmd_value; break;
|
|
|
|
case TRIGGER_CMD_MODE: {
|
|
|
|
TriggerModeUnion new_mode_union;
|
|
|
|
new_mode_union.common = header.bits.cmd_value;
|
|
|
|
const TRIGER_MODE new_mode = static_cast<TRIGER_MODE> (new_mode_union.bits.mode);
|
|
|
|
if (m_settings.mode != new_mode) m_settings.mode = new_mode;
|
|
|
|
const ADC_CHANNELS new_channel = static_cast<ADC_CHANNELS>(new_mode_union.bits.channel);
|
|
|
|
if (m_settings.channel != new_channel) m_settings.channel = new_channel;
|
|
|
|
const bool new_rising = new_mode_union.bits.rissing ? true : false;
|
|
|
|
if (m_settings.rising != new_rising) m_settings.rising = new_rising;
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SampleRing::write(DATA_BLOCK const * data) {
|
|
|
|
if (m_finished) return;
|
2024-10-22 20:05:15 +02:00
|
|
|
/** Tady je problém - tato funkce běží pod přerušením s vyšší prioritou,
|
2024-10-22 17:07:37 +02:00
|
|
|
* takže m_mode se během tt. funkce změnit nemůže. Z toho vyplývá, že se
|
|
|
|
* odeslání dat musí vykonat a nelze tedy změnit m_mode dokud se data
|
2024-10-22 20:05:15 +02:00
|
|
|
* meodešlou do ring_buffer všechna.
|
2024-10-22 17:07:37 +02:00
|
|
|
* */
|
2024-10-22 20:05:15 +02:00
|
|
|
if (m_mode != o_mode) { // bug fix
|
|
|
|
if (m_mode == TIME_BASE_CONTINUOUS) { // Při změně na kontinuální provoz
|
|
|
|
m_lenght = RING_LEN; // odešli celý ring_buffer.
|
|
|
|
m_tail = m_head; // Není to ideální, ale funguje to.
|
|
|
|
m_finished = true; // Příkaz k odeslání to odstartuje.
|
|
|
|
}
|
|
|
|
o_mode = m_mode;
|
|
|
|
return;
|
|
|
|
}
|
2024-10-21 10:26:41 +02:00
|
|
|
unsigned t_head = m_head; // dočasné proměnné kvůli zrychlení
|
|
|
|
unsigned t_lenght = m_lenght; // následujícího cyklu
|
|
|
|
if (m_mode == TIME_BASE_TRIGERED) {
|
|
|
|
for (unsigned n=0u; n<DATA_HALF_LEN; n++) {
|
|
|
|
const DATA_BLOCK & sample = data [n];
|
|
|
|
ring_buffer [t_head].common_data = sample.common_data;
|
|
|
|
t_head += 1u;
|
|
|
|
t_head &= RING_MSK;
|
|
|
|
t_lenght += 1u;
|
|
|
|
const bool compare = m_settings.rising != (sample.channels[m_settings.channel] > m_settings.value);
|
|
|
|
if (compare and m_old_triger and !m_trigered) { // TRIGERED
|
|
|
|
if (t_lenght >= m_settings.offset) {
|
|
|
|
t_lenght = m_settings.offset;
|
|
|
|
m_trigered = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_old_triger = !compare;
|
2024-10-22 17:07:37 +02:00
|
|
|
if (t_lenght >= RING_LEN) { // je fuk o kolik je to delší
|
2024-10-21 10:26:41 +02:00
|
|
|
// zastavit odesílání dat, pokud není AUTO a není splněna podmínka trigeru
|
|
|
|
if ((m_settings.mode != TRIGER_MODE_AUTO) and !m_trigered) continue;
|
|
|
|
t_lenght = RING_LEN;
|
|
|
|
m_tail = t_head;
|
|
|
|
m_finished = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
const DATA_BLOCK & sample = data [0];
|
|
|
|
ring_buffer [t_head].common_data = sample.common_data;
|
2024-10-22 17:07:37 +02:00
|
|
|
t_head += 1u;
|
|
|
|
t_head &= RING_MSK;
|
|
|
|
t_lenght += 1u;
|
2024-10-21 10:26:41 +02:00
|
|
|
m_finished = true;
|
|
|
|
}
|
|
|
|
m_head = t_head; // vrať zpátky hodnoty
|
|
|
|
m_lenght = t_lenght;
|
|
|
|
}
|
|
|
|
bool SampleRing::read(DATA_BLOCK & sample) {
|
|
|
|
if (!m_finished) return false;
|
|
|
|
if (!m_lenght) {
|
|
|
|
m_head = m_tail = m_lenght = 0u;
|
|
|
|
m_trigered = false;
|
|
|
|
m_finished = false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
sample = ring_buffer [m_tail];
|
|
|
|
m_tail += 1u;
|
|
|
|
m_tail &= RING_MSK;
|
|
|
|
m_lenght -= 1u;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
uint32_t SampleRing::BlockSend (const char * buf, const uint32_t len) {
|
|
|
|
uint32_t n, ofs = 0, req = len;
|
|
|
|
for (;;) {
|
|
|
|
// spodní vrstva může vrátit i nulu, pokud je FIFO plné
|
|
|
|
n = BaseLayer::Down (buf + ofs, req);
|
|
|
|
ofs += n; // Posuneme ukazatel
|
|
|
|
req -= n; // Zmenšíme další požadavek
|
|
|
|
if (!req) break;
|
|
|
|
}
|
|
|
|
return ofs;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SampleRing::pass() {
|
2024-10-22 17:07:37 +02:00
|
|
|
if (!m_finished) return;
|
2024-10-21 10:26:41 +02:00
|
|
|
SendPrefix();
|
|
|
|
DATA_BLOCK data;
|
|
|
|
while (read(data)) {
|
|
|
|
SendData (data);
|
|
|
|
}
|
|
|
|
BlockSend("\r\n", 2);
|
|
|
|
}
|
|
|
|
static int to_str (char * buffer, const uint16_t data, const int len = 3) {
|
|
|
|
unsigned val = data;
|
|
|
|
for (int i=len-1; i>=0; --i) {
|
|
|
|
buffer [i] = hexstr [val & 0xF];
|
|
|
|
val >>= 4;
|
|
|
|
}
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
uint32_t SampleRing::SendPrefix() {
|
|
|
|
const int buflen = 8;
|
|
|
|
char buffer [buflen];
|
|
|
|
int n = 0;
|
|
|
|
buffer [n++] = '$';
|
|
|
|
SendHeader sh;
|
|
|
|
sh.bits.trig_flg = m_trigered ? 1 : 0;
|
|
|
|
sh.bits.pack_len = m_lenght;
|
|
|
|
n += to_str (buffer + n, sh.common, 4);
|
|
|
|
buffer [n++] = '#';
|
|
|
|
return BlockSend (buffer, n);
|
|
|
|
}
|
|
|
|
uint32_t SampleRing::SendData (const DATA_BLOCK & data) {
|
|
|
|
const int buflen = 8;
|
|
|
|
char buffer [buflen];
|
|
|
|
int n = 0;
|
|
|
|
n += to_str (buffer + n, data.channels[0]);
|
|
|
|
n += to_str (buffer + n, data.channels[1]);
|
|
|
|
return BlockSend (buffer, n);
|
|
|
|
}
|
|
|
|
|