TX iterator now implemented in AFSK TX. FSK TX WIP.

pull/4/head
CInsights 2018-03-26 13:07:11 +11:00
rodzic 393a1d59b5
commit 9fccfd3271
6 zmienionych plików z 556 dodań i 188 usunięć

Wyświetl plik

@ -5,7 +5,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider copy-of="extension" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser"/>
<provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="461136237790816521" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="138446027592133826" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>

Wyświetl plik

@ -483,38 +483,36 @@ bool Si446x_setBandParameters(uint32_t freq,
break;
} /* End switch. */
/* Set the band parameter. */
uint32_t sy_sel = 8;
uint8_t set_band_property_command[] = {0x11, 0x20, 0x01, 0x51, (band + sy_sel)};
Si446x_write(set_band_property_command, 5);
/* Set the PLL parameters. */
uint32_t f_pfd = 2 * Si446x_CCLK / outdiv;
uint32_t n = ((uint32_t)(freq / f_pfd)) - 1;
float ratio = (float)freq / (float)f_pfd;
float rest = ratio - (float)n;
/* Set the band parameter. */
uint32_t sy_sel = 8;
uint8_t set_band_property_command[] = {0x11, 0x20, 0x01, 0x51, (band + sy_sel)};
Si446x_write(set_band_property_command, 5);
uint32_t m = (uint32_t)(rest * 524288UL);
uint32_t m2 = m >> 16;
uint32_t m1 = (m - m2 * 0x10000) >> 8;
uint32_t m0 = (m - m2 * 0x10000 - (m1 << 8));
/* Set the PLL parameters. */
uint32_t f_pfd = 2 * Si446x_CCLK / outdiv;
uint32_t n = ((uint32_t)(freq / f_pfd)) - 1;
float ratio = (float)freq / (float)f_pfd;
float rest = ratio - (float)n;
uint32_t channel_increment = 524288 * outdiv * step / (2 * Si446x_CCLK);
uint8_t c1 = channel_increment / 0x100;
uint8_t c0 = channel_increment - (0x100 * c1);
uint32_t m = (uint32_t)(rest * 524288UL);
uint32_t m2 = m >> 16;
uint32_t m1 = (m - m2 * 0x10000) >> 8;
uint32_t m0 = (m - m2 * 0x10000 - (m1 << 8));
uint8_t set_frequency_property_command[] = {0x11, 0x40, 0x04, 0x00, n, m2, m1, m0, c1, c0};
Si446x_write(set_frequency_property_command, 10);
uint32_t channel_increment = 524288 * outdiv * step / (2 * Si446x_CCLK);
uint8_t c1 = channel_increment / 0x100;
uint8_t c0 = channel_increment - (0x100 * c1);
uint8_t set_frequency_property_command[] = {0x11, 0x40, 0x04, 0x00, n, m2, m1, m0, c1, c0};
Si446x_write(set_frequency_property_command, 10);
uint32_t x = ((((uint32_t)1 << 19) * outdiv * 1300.0)/(2*Si446x_CCLK))*2;
uint8_t x2 = (x >> 16) & 0xFF;
uint8_t x1 = (x >> 8) & 0xFF;
uint8_t x0 = (x >> 0) & 0xFF;
uint8_t set_deviation[] = {0x11, 0x20, 0x03, 0x0a, x2, x1, x0};
Si446x_write(set_deviation, 7);
return true;
uint32_t x = ((((uint32_t)1 << 19) * outdiv * 1300.0)/(2*Si446x_CCLK))*2;
uint8_t x2 = (x >> 16) & 0xFF;
uint8_t x1 = (x >> 8) & 0xFF;
uint8_t x0 = (x >> 0) & 0xFF;
uint8_t set_deviation[] = {0x11, 0x20, 0x03, 0x0a, x2, x1, x0};
Si446x_write(set_deviation, 7);
return true;
}
/*static void Si446x_setShift(uint16_t shift)
@ -985,7 +983,7 @@ static uint32_t Si446x_encodeDataToAFSK(uint8_t *inbuf, uint32_t inlen,
uint32_t blen = 0;
// Preamble (HDLC flags)
for(uint8_t i = 0; i <= pre_len; i++) {
for(uint8_t i = 0; i < pre_len; i++) {
for(uint8_t j = 0; j < 8; j++) {
if(blen >> 3 >= buf_len) { // Buffer overflow
@ -1098,10 +1096,10 @@ static uint8_t Si446x_getUpsampledAFSKbits(uint8_t* buf/*, uint32_t blen*/)
return b;
}
static void Si446x_upsampleAFSKstream(uint8_t current_byte,
static void Si446x_upsampleNRZIstream(uint8_t current_byte,
uint8_t *buf,
uint8_t upsample_rate) {
uint8_t b = 0, i = 0, usr = 0;
uint8_t b = 0, i = 0, usr;
for(usr = 0; usr < upsample_rate; usr++) {
do {
// Toggle tone (1200 <> 2200)
@ -1109,19 +1107,24 @@ static void Si446x_upsampleAFSKstream(uint8_t current_byte,
/* Add delta-phase (bit count within SAMPLES_PER_BAUD). */
phase += phase_delta;
b |= ((phase >> 16) & 1) << i; // Set modulation bit
} while(++i != 8);
current_byte >>= (i * 8) / upsample_rate;
current_byte >>= (usr / upsample_rate) * 8;
} while(++i < 8);
i = 0;
buf[usr] = b;
}
}
#define SI446X_EVT_AFSK_TX_TIMEOUT EVENT_MASK(0)
static void Si446x_AFSKtransmitTimeoutI(thread_t *tp) {
static void Si446x_transmitTimeoutI(thread_t *tp) {
/* The tell the thread to terminate. */
chEvtSignal(tp, SI446X_EVT_AFSK_TX_TIMEOUT);
}
/*
* Original AFSK send thread.
*/
THD_FUNCTION(si_fifo_feeder_afsk, arg) {
packet_t pp = arg;
@ -1194,7 +1197,7 @@ THD_FUNCTION(si_fifo_feeder_afsk, arg) {
* If the 446x gets locked up we'll exit TX and release packet object.
*/
chVTSet(&send_timer, TIME_S2I(10),
(vtfunc_t)Si446x_AFSKtransmitTimeoutI, chThdGetSelfX());
(vtfunc_t)Si446x_transmitTimeoutI, chThdGetSelfX());
/* The exit message if all goes well. */
msg_t exit_msg = MSG_OK;
@ -1257,7 +1260,8 @@ THD_FUNCTION(si_fifo_feeder_afsk, arg) {
}
/*
* AFSK transmit manager thread.
* Experimental AFSK transmit manager thread.
* Currently broken....
*/
THD_FUNCTION(new_si_fifo_feeder_afsk, arg) {
packet_t pp = arg;
@ -1269,19 +1273,13 @@ THD_FUNCTION(new_si_fifo_feeder_afsk, arg) {
/* Initialize variables for AFSK encoder. */
virtual_timer_t send_timer;
chVTObjectInit(&send_timer);
//uint8_t layer0[AFSK_FEEDER_BUFFER_SIZE];
TRACE_INFO("SI > Packet frame bytes %i", pp->frame_len);
static tx_iterator_t iterator;
pktStreamIteratorInit(&iterator, pp, false);
tx_iterator_t iterator;
pktStreamIteratorInit(&iterator, pp, 30, 10, 10, false);
uint16_t all = pktStreamEncodingIterator(&iterator, NULL, 0);
TRACE_INFO("SI > Packet stream bytes %i", all);
#ifdef TX_ITERATOR_VERIFICATION
@ -1310,98 +1308,276 @@ THD_FUNCTION(new_si_fifo_feeder_afsk, arg) {
TRACE_ERROR("SI > Encoding results differ at index %i, layer0 0x%x, layer1 0x%x", i, layer0[i], layer1[i]);
}
#endif
TRACE_INFO("SI > AFSK frame bytes to send %i, upsampled %i",
TRACE_INFO("SI > AFSK frame bytes to send %i, up-sampled %i",
all, all * SAMPLES_PER_BAUD);
//#define TEMP_ITERATOR_TEST
#ifndef TEMP_ITERATOR_TEST
/*
* Start transmission timeout timer.
* If the 446x gets locked up we'll exit TX and release packet object.
*/
/* chVTSet(&send_timer, TIME_S2I(3),
(vtfunc_t)Si446x_AFSKtransmitTimeoutI, chThdGetSelfX());*/
#endif
/*
* Get the maximum size of the FIFO.
* Create an NRZI buffer based on maximum FIFO capacity.
*/
/* Reset TX FIFO to clear it and get maximum capacity. */
const uint8_t reset_fifo[] = {0x15, 0x01};
Si446x_write(reset_fifo, 2);
uint8_t max = Si446x_getTXfreeFIFO();
uint8_t load = max / SAMPLES_PER_BAUD;
uint8_t nrzi[load];
/* Create an interim FIFO load buffer. */
uint8_t localBuffer[max];
memset(localBuffer, 0, sizeof(localBuffer));
uint16_t data = pktStreamEncodingIterator(&iterator, nrzi, load);
/* Initial FIFO load. */
uint16_t i;
for(i = 0; i < (data * SAMPLES_PER_BAUD); i++)
localBuffer[i] = Si446x_getUpsampledAFSKbits(nrzi);
Si446x_writeFIFO(localBuffer, i);
/*
* Initialize variables for up sampler.
* TODO: Use an up-sampler object.
*/
phase_delta = PHASE_DELTA_1200;
phase = 0;
packet_pos = 0;
current_sample_in_baud = 0;
current_byte = 0;
uint8_t lower = Si446x_FIFO_COMBINED_SIZE;
uint8_t lower = max;
/* The FIFO size required to output one stream byte. */
uint8_t localBuffer[SAMPLES_PER_BAUD];
memset(localBuffer, 0, sizeof(localBuffer));
/* The exit message if all goes well. */
msg_t exit_msg = MSG_OK;
bool tx_started = false;
/* Reset TX FIFO in case some remnant unsent data is left there. */
const uint8_t reset_fifo[] = {0x15, 0x01};
Si446x_write(reset_fifo, 2);
/* The exit message if TX times out. */
msg_t exit_msg = MSG_TIMEOUT;
eventmask_t evt = 0;
/*
* Start transmission timeout timer.
* If the 446x gets locked up we'll exit TX and release packet object.
*/
/* chVTSet(&send_timer, TIME_S2I(3),
(vtfunc_t)Si446x_AFSKtransmitTimeoutI, chThdGetSelfX());*/
/*
* Wait in a timeout event during up-sampled AFSK byte time period.
* Time delay allows for ~11 bytes of transmit data from the FIFO.
* If no timeout event continue and check for sufficient FIFO space.
*/
while((evt = chEvtWaitAnyTimeout(SI446X_EVT_AFSK_TX_TIMEOUT,
chTimeUS2I(833 * 8 * SAMPLES_PER_BAUD))) == 0) {
chTimeUS2I(833 * 8))) == 0) {
uint8_t more = Si446x_getTXfreeFIFO();
/* Update the FIFO low water mark. */
lower = (more < lower) ? more : lower;
if(more < SAMPLES_PER_BAUD)
continue;
#define IT_BYTES 1
uint8_t byte[IT_BYTES];
uint16_t data = 0;
#ifdef TEMP_ITERATOR_TEST
uint16_t count = 0;
while(iterator.state != ITERATE_END) {
data = pktStreamEncodingIterator(&iterator, byte, IT_BYTES);
TRACE_INFO("SI > Iterator byte 0x%02x, data %i, all %03i, index %03i, "
"state %i, HDLC %03i, RLL %02i, data %03i, out index 0x%05x",
byte[0], data, all, ++count, iterator.state,
iterator.hdlc_count, iterator.rll_count,
iterator.data_size, iterator.out_index);
chThdSleep(TIME_MS2I(500));
}
do {
data = pktStreamEncodingIterator(&iterator, nrzi, CHUNK_SIZE);
count++;
TRACE_INFO("SI > Iterator byte 0x%02x, data %03i, all %03i, "
"index %03i, state %i, HDLC %03i, RLL %02i, data %03i, "
"out index 0x%05x, in index 0x%05x",
nrzi[0], data, all, count, iterator.state,
iterator.hdlc_count, iterator.rll_count,
iterator.data_size, iterator.out_index,
iterator.inp_index);
chThdSleep(TIME_MS2I(100));
} while(iterator.state != ITERATE_END);
break;
#if 0
if((data = pktStreamEncodingIterator(&iterator, byte, 1)) == 0) {
#else
data = pktStreamEncodingIterator(&iterator, nrzi,
(more / SAMPLES_PER_BAUD));
if(data == 0) {
/* All data streamed. */
exit_msg = MSG_OK;
break;
}
/* Load the interim buffer and transfer to FIFO. */
Si446x_upsampleAFSKstream(byte[0], localBuffer,
SAMPLES_PER_BAUD);
Si446x_writeFIFO(localBuffer, SAMPLES_PER_BAUD); // Write into FIFO
TRACE_INFO("SI > Transmit AFSK stream byte with FIFO %i", more);
/* Load the FIFO. */
packet_pos = 0;
current_sample_in_baud = 0;
uint16_t i;
for(i = 0; i < (data * SAMPLES_PER_BAUD); i++)
localBuffer[i] = Si446x_getUpsampledAFSKbits(nrzi);
Si446x_writeFIFO(localBuffer, i); // Write into FIFO
if(!tx_started) {
/* Request start of transmission. */
if(!Si446x_transmit(pp->radio_chan, pp->radio_pwr, all,
if(!Si446x_transmit(pp->radio_chan, pp->radio_pwr,
all * SAMPLES_PER_BAUD,
pp->cca_rssi, TIME_S2I(10))) {
exit_msg = MSG_RESET;
break;
} /* Else. */
tx_started = true;
tx_started = true;
}
#endif
} /* End while. */
/* Arrive here on break from while or TX timeout. */
/* Arrive here on break from while, TX transmit error or TX timeout. */
if(exit_msg != MSG_OK) {
/* Force 446x out of TX state. */
Si446x_setReadyState();
} else {
/*
* If nothing went wrong wait for TX to finish.
*/
while(Si446x_getState() == Si446x_STATE_TX) {
/* Sleep for an AFSK byte time. */
chThdSleep(chTimeUS2I(833 * 8));
continue;
}
}
/* Stop transmit timeout timer. */
chVTReset(&send_timer);
// Free packet object memory
pktReleaseSendObject(pp);
TRACE_INFO("SI > TX FIFO lowest level %i", lower);
/* Exit thread. */
chThdExit(exit_msg);
}
/*
* Simple AFSK send thread using minimized buffering.
* Uses an iterator to size NRZI output and allocate suitably sized buffer.
* Plan is to replace with a version using even less memory.
*
*/
THD_FUNCTION(min_si_fifo_feeder_afsk, arg) {
packet_t pp = arg;
#if USE_DYNAMIC_AFSK_TX != TRUE
chRegSetThreadName("446x_afsk_tx");
#endif
/* Initialize variables for AFSK encoder. */
virtual_timer_t send_timer;
chVTObjectInit(&send_timer);
tx_iterator_t iterator;
pktStreamIteratorInit(&iterator, pp, 30, 10, 10, false);
uint16_t all = pktStreamEncodingIterator(&iterator, NULL, 0);
TRACE_INFO("SI > Packet stream bytes %i", all);
if(all == 0) {
/* Nothing encoded. Release packet send object. */
pktReleaseSendObject(pp);
/* Exit thread. */
chThdExit(MSG_RESET);
}
/* Allocate buffer and perform NRZI encoding. */
uint8_t layer0[all];
memset(layer0, 0, sizeof(layer0));
pktStreamEncodingIterator(&iterator, layer0, all);
/* TRACE_INFO("SI > Iterator out count %i, bytes %i, out bits %i",
iterator.out_count, iterator.out_index >> 3,
iterator.out_index % 8);*/
//#define TX_ITERATOR_VERIFICATION_MIN
#ifdef TX_ITERATOR_VERIFICATION_MIN
uint8_t layer1[all + 1];
memset(layer1, 0, sizeof(layer1));
ctone = 0;
uint32_t layer1_blen = Si446x_encodeDataToAFSK(pp->frame_data,
pp->frame_len,
layer1, sizeof(layer1),
50);
TRACE_INFO("SI > Encoder out count %i, bytes %i, out bits %i",
(layer1_blen + 7) >> 3, layer1_blen >> 3, layer1_blen % 8);
bool diff = false;
uint16_t end = (layer1_blen + 7) >> 3;
uint16_t i;
for (i = 0; i < end; i++) {
if (layer0[i] != layer1[i]) {
diff = true;
break;
}
}
if(diff) {
TRACE_ERROR("SI > Encoding results differ at index %i, layer0 0x%x, layer1 0x%x", i, layer0[i], layer1[i]);
}
#endif
all *= SAMPLES_PER_BAUD;
/* Reset TX FIFO in case some remnant unsent data is left there. */
const uint8_t reset_fifo[] = {0x15, 0x01};
Si446x_write(reset_fifo, 2);
/* Initialize variables for up sampler. */
phase_delta = PHASE_DELTA_1200;
phase = 0;
packet_pos = 0;
current_sample_in_baud = 0;
current_byte = 0;
/* Maximum amount of FIFO data when using combined TX+RX (safe size). */
uint8_t localBuffer[Si446x_FIFO_COMBINED_SIZE];
/* Get the FIFO buffer amount currently available. */
uint8_t free = Si446x_getTXfreeFIFO();
/* Calculate initial FIFO fill. */
uint16_t c = (all > free) ? free : all;
/*
* Start transmission timeout timer.
* If the 446x gets locked up we'll exit TX and release packet object.
*/
chVTSet(&send_timer, TIME_S2I(10),
(vtfunc_t)Si446x_transmitTimeoutI, chThdGetSelfX());
/* The exit message if all goes well. */
msg_t exit_msg = MSG_OK;
/* Initial FIFO load. */
for(uint16_t i = 0; i < c; i++)
localBuffer[i] = Si446x_getUpsampledAFSKbits(layer0);
Si446x_writeFIFO(localBuffer, c);
uint8_t lower = 0;
/* Request start of transmission. */
if(Si446x_transmit(pp->radio_chan, pp->radio_pwr, all,
pp->cca_rssi, TIME_S2I(10))) {
/* Feed the FIFO while data remains to be sent. */
while((all - c) > 0) {
/* Get TX FIFO free count. */
uint8_t more = Si446x_getTXfreeFIFO();
/* Update the FIFO free low water mark. */
lower = (more > lower) ? more : lower;
/* If there is more free than we need for send use remainder only. */
more = (more > (all - c)) ? (all - c) : more;
/* Load the FIFO. */
for(uint16_t i = 0; i < more; i++)
localBuffer[i] = Si446x_getUpsampledAFSKbits(layer0);
Si446x_writeFIFO(localBuffer, more); // Write into FIFO
c += more;
/*
* Wait for a timeout event during up-sampled NRZI send.
* Time delay allows ~SAMPLES_PER_BAUD bytes to be consumed from FIFO.
* If no timeout event go back and load more data to FIFO.
*/
eventmask_t evt = chEvtWaitAnyTimeout(SI446X_EVT_AFSK_TX_TIMEOUT,
chTimeUS2I(833 * 8));
if(evt) {
/* Force 446x out of TX state. */
Si446x_setReadyState();
exit_msg = MSG_TIMEOUT;
break;
}
}
} else {
/* Transmit start failed. */
TRACE_ERROR("SI > Transmit start failed");
}
chVTReset(&send_timer);
@ -1410,15 +1586,15 @@ THD_FUNCTION(new_si_fifo_feeder_afsk, arg) {
* Else don't wait.
*/
while(Si446x_getState() == Si446x_STATE_TX && exit_msg == MSG_OK) {
/* Sleep for an AFSK up-sampled byte time. */
chThdSleep(chTimeUS2I(833 * 8 * SAMPLES_PER_BAUD));
/* Sleep for an AFSK byte time. */
chThdSleep(chTimeUS2I(833 * 8));
continue;
}
// Free packet object memory
pktReleaseSendObject(pp);
TRACE_INFO("SI > TX FIFO lowest level %i", lower);
TRACE_INFO("SI > TX FIFO lowest free level %i", lower);
/* Exit thread. */
chThdExit(exit_msg);
@ -1449,14 +1625,10 @@ void Si446x_sendAFSK(packet_t pp,
#if USE_DYNAMIC_AFSK_TX == TRUE
afsk_feeder_thd = chThdCreateFromHeap(NULL,
#ifdef TX_ITERATOR_VERIFICATION
THD_WORKING_AREA_SIZE(SI_AFSK_FIFO_FEEDER_WA_SIZE * 2),
#else
THD_WORKING_AREA_SIZE(SI_AFSK_FIFO_FEEDER_WA_SIZE),
#endif
THD_WORKING_AREA_SIZE(SI_AFSK_FIFO_MIN_FEEDER_WA_SIZE),
"446x_afsk_tx",
NORMALPRIO - 10,
si_fifo_feeder_afsk,
min_si_fifo_feeder_afsk,
pp);
#else
// Start/re-start FIFO feeder
@ -1498,6 +1670,9 @@ void Si446x_stopDecoder(void) {
/* ========================================================================== 2FSK ========================================================================== */
/*
* Old 2FSK send thread.
*/
THD_FUNCTION(si_fifo_feeder_fsk, arg) {
packet_t pp = arg;
@ -1546,6 +1721,134 @@ THD_FUNCTION(si_fifo_feeder_fsk, arg) {
chThdExit(MSG_OK);
}
/*
* New 2FSK send thread using minimised buffer space.
*/
THD_FUNCTION(min_si_fifo_feeder_fsk, arg) {
packet_t pp = arg;
#if USE_DYNAMIC_FSK_TX != TRUE
chRegSetThreadName("446x_2fsk_tx");
#endif
/* Initialize variables for 2FSK encoder. */
virtual_timer_t send_timer;
chVTObjectInit(&send_timer);
tx_iterator_t iterator;
pktStreamIteratorInit(&iterator, pp, 30, 10, 10, false);
/* Compute size of NRZI stream. */
uint16_t all = pktStreamEncodingIterator(&iterator, NULL, 0);
TRACE_INFO("SI > Packet stream bytes %i", all);
if(all == 0) {
/* Nothing encoded. Release packet send object. */
pktReleaseSendObject(pp);
/* Exit thread. */
chThdExit(MSG_RESET);
}
/* Allocate buffer and perform NRZI encoding. */
uint8_t layer0[all];
memset(layer0, 0, sizeof(layer0));
pktStreamEncodingIterator(&iterator, layer0, all);
/* Reset TX FIFO in case some remnant unsent data is left there. */
const uint8_t reset_fifo[] = {0x15, 0x01};
Si446x_write(reset_fifo, 2);
/* Initialize variables for up sampler. */
phase_delta = PHASE_DELTA_1200;
phase = 0;
packet_pos = 0;
current_sample_in_baud = 0;
current_byte = 0;
/* Get the FIFO buffer amount currently available. */
uint8_t free = Si446x_getTXfreeFIFO();
/* Calculate initial FIFO fill. */
uint16_t c = (all > free) ? free : all;
/*
* Start transmission timeout timer.
* If the 446x gets locked up we'll exit TX and release packet object.
*/
chVTSet(&send_timer, TIME_S2I(10),
(vtfunc_t)Si446x_transmitTimeoutI, chThdGetSelfX());
/* The exit message if all goes well. */
msg_t exit_msg = MSG_OK;
uint8_t *bufp = layer0;
/* Initial FIFO load. */
Si446x_writeFIFO(bufp, c);
bufp += c;
uint8_t lower = 0;
/* Request start of transmission. */
if(Si446x_transmit(pp->radio_chan, pp->radio_pwr, all,
pp->cca_rssi, TIME_S2I(10))) {
/* Feed the FIFO while data remains to be sent. */
while((all - c) > 0) {
/* Get TX FIFO free count. */
uint8_t more = Si446x_getTXfreeFIFO();
/* Update the FIFO free low water mark. */
lower = (more > lower) ? more : lower;
/* If there is more free than we need for send use remainder only. */
more = (more > (all - c)) ? (all - c) : more;
/* Load the FIFO. */
Si446x_writeFIFO(bufp, more); // Write into FIFO
bufp += more;
c += more;
/*
* Wait for a timeout event during up-sampled NRZI send.
* Time delay allows ~10 bytes to be consumed from FIFO.
* If no timeout event go back and load more data to FIFO.
*/
eventmask_t evt = chEvtWaitAnyTimeout(SI446X_EVT_AFSK_TX_TIMEOUT,
chTimeUS2I(104 * 8 * 10));
if(evt) {
/* Force 446x out of TX state. */
Si446x_setReadyState();
exit_msg = MSG_TIMEOUT;
break;
}
}
} else {
/* Transmit start failed. */
TRACE_ERROR("SI > Transmit start failed");
}
chVTReset(&send_timer);
/*
* If nothing went wrong wait for TX to finish.
* Else don't wait.
*/
while(Si446x_getState() == Si446x_STATE_TX && exit_msg == MSG_OK) {
/* Sleep for a 2FSK byte time. */
chThdSleep(chTimeUS2I(104 * 8 * 10));
continue;
}
// Free packet object memory
pktReleaseSendObject(pp);
TRACE_INFO("SI > TX FIFO lowest free level %i", lower);
/* Exit thread. */
chThdExit(exit_msg);
}
void Si446x_send2FSK(packet_t pp,
uint8_t chan,
uint8_t pwr,
@ -1568,7 +1871,7 @@ void Si446x_send2FSK(packet_t pp,
fsk_feeder_thd = chThdCreateStatic(si_fsk_fifo_feeder_wa,
sizeof(si_fsk_fifo_feeder_wa),
HIGHPRIO,
si_fifo_feeder_fsk,
min_si_fifo_feeder_fsk,
pp);
msg_t send_msg = chThdWait(fsk_feeder_thd);

Wyświetl plik

@ -192,6 +192,7 @@
#define AFSK_FEEDER_BUFFER_SIZE 3072
#define USE_DYNAMIC_AFSK_TX TRUE
#define SI_AFSK_FIFO_FEEDER_WA_SIZE (AFSK_FEEDER_BUFFER_SIZE + 1024)
#define SI_AFSK_FIFO_MIN_FEEDER_WA_SIZE 1024
#define USE_DYNAMIC_FSK_TX FALSE
#define SI_FSK_FIFO_FEEDER_WA_SIZE 4096

Wyświetl plik

@ -56,7 +56,7 @@ eventmask_t evt = chEvtGetAndClearEvents(EVENT_MASK(1));
TRACE_WARN("PKT > PWM ICU overflow");
}
if(flags & EVT_PWM_STREAM_TIMEOUT) {
TRACE_WARN("PKT > PWM steam timeout");
TRACE_WARN("PKT > PWM stream timeout");
}
if(flags & EVT_PWM_NO_DATA) {
TRACE_WARN("PKT > PWM data not started from radio");

Wyświetl plik

@ -8,15 +8,31 @@
#include "pktconf.h"
/*
* Initialize the iterator object.
* TODO: Preamble count to come from config.
/**
* @brief Initialize an NRZI stream iterator.
* @post The iterator is ready for use.
* @notes Preamble size is a fixed value currently.
*
* @param[in] iterator pointer to an @p iterator object.
* @param[in] pp packet object reference pointer.
* @param[in] pre length of HDLC (falgs) preamble
* @param[in] post length of HDLC (flags) closing
* @param[in] tail length of HDLC (0) tail flags
* @param[in] scramble determines if scrambling (whitening) is applied.
*
* @api
*/
void pktStreamIteratorInit(tx_iterator_t *iterator,
packet_t pp, bool scramble) {
packet_t pp,
uint8_t pre,
uint8_t post,
uint8_t tail,
bool scramble) {
memset(iterator, 0, sizeof(tx_iterator_t));
iterator->hdlc_code = HDLC_FLAG;
iterator->hdlc_count = 50;
iterator->hdlc_count = pre;
iterator->hdlc_post = post;
iterator->hdlc_tail = tail;
iterator->scramble = scramble;
iterator->data_buff = pp->frame_data;
iterator->data_size = pp->frame_len;
@ -28,18 +44,27 @@ void pktStreamIteratorInit(tx_iterator_t *iterator,
}
/*
* Write NRZI data to output buffer.
* Scrambling is applied if selected.
/**
* @brief Write NRZI stream data to buffer.
* @post NRZI encoded bits are written to the stream.
* @notes If counting only is active data is not written but simply counted.
*
* @param[in] iterator pointer to an @p iterator object.
* @param[in] bit the bit to be written.
*
* @return status.
* @retval true indicates the requested quantity of bytes has been reached.
* @retval false indicates the requested quantity of bytes not reached.
*
* @notapi
*/
static bool pktIteratorWriteStream(tx_iterator_t *iterator, uint8_t bit) {
static bool pktIteratorWriteStreamBit(tx_iterator_t *iterator, uint8_t bit) {
/* If new output buffer byte clear it first if write is enabled. */
if((iterator->out_index % 8 == 0) && (iterator->no_write == false))
iterator->out_buff[iterator->out_index >> 3] = 0;
/* Normalize to bit 0. */
if(bit != 0) bit = 1;
/* Mask to bit 0 only. */
bit &= 1;
/* Keep track of HDLC for RLL detection. */
iterator->hdlc_hist <<= 1;
@ -47,6 +72,7 @@ static bool pktIteratorWriteStream(tx_iterator_t *iterator, uint8_t bit) {
if(iterator->scramble) {
iterator->lfsr <<= 1;
/* Scramble is ^16 and ^11 but we shifted up one. */
iterator->lfsr |= (bit ^ (iterator->lfsr >> 17)
^ (iterator->lfsr >> 12)) & 0x1;
bit = iterator->lfsr & 0x1;
@ -60,58 +86,72 @@ static bool pktIteratorWriteStream(tx_iterator_t *iterator, uint8_t bit) {
iterator->out_buff[iterator->out_index >> 3] |=
(iterator->nrzi_hist & 0x1) << (iterator->out_index % 8);
/* If byte was completed check quantity status. */
if((iterator->inp_index % 8) == 0) {
if((++iterator->out_count) == iterator->qty) {
//iterator->out_index = 0;
/* If byte was filled then check quantity status. */
if((++iterator->out_index % 8) == 0) {
if((++iterator->out_count) == iterator->qty)
return true;
}
}
return false;
}
/*
/**
* @brief Encode frame HDLC byte.
* @pre Iterator object initialized and buffer pointer set.
* @post HDLC octet is written to the stream unless counting only is active.
*
* @param[in] iterator pointer to an @p iterator object.
*
* @return status.
* @retval true indicates the requested quantity of bytes has been reached.
* @retval false indicates the requested quantity of bytes not reached.
*
* @notapi
*/
static bool pktEncodeFrameHDLC(tx_iterator_t *iterator) {
do {
iterator->inp_index++;
if(pktIteratorWriteStream(iterator,
((iterator->hdlc_code >> iterator->hdlc_bit++) & 0x1)
<< (iterator->out_index % 8))) {
if(iterator->hdlc_bit == 8)
iterator->hdlc_bit = 0;
uint8_t bit = (iterator->hdlc_code >> (iterator->inp_index++ % 8)) & 0x1;
if((iterator->inp_index % 8) == 0)
iterator->hdlc_count--;
if(pktIteratorWriteStreamBit(iterator, bit))
return true;
}
} while(iterator->hdlc_bit < 8);
iterator->hdlc_bit = 0;
} while((iterator->inp_index % 8) != 0);
return false;
}
/*
/**
* @brief Encode frame data byte.
* @pre Iterator object initialized and buffer pointer set.
* @post Data is written to the stream unless counting only is active.
* @notes Data size may expand due to RLL encoding.
* @notes The required quantity may be reached on a RLL inserted bit.
*
* @param[in] iterator pointer to an @p iterator object.
*
* @return status.
* @retval true indicates the requested quantity of bytes has been reached.
* @retval false indicates the requested quantity of bytes not reached.
*
* @notapi
*/
static bool pktEncodeFrameData(tx_iterator_t *iterator) {
do {
/* Get data bit. */
uint8_t byte = iterator->data_buff[iterator->inp_index >> 3];
uint8_t bit = (byte >> (iterator->inp_index % 8)) & 0x1;
/* Indicate data input bit is consumed. Write to stream. */
iterator->inp_index++;
if(pktIteratorWriteStream(iterator, bit))
return true;
/* RLL encoding is enabled for the packet data pay load. */
/* Next apply RLL encoding for the packet data pay load. */
if((iterator->hdlc_hist & HDLC_RLL_SEQUENCE) == HDLC_RLL_SEQUENCE) {
iterator->rll_count++;
/* Insert RLL 0 to output stream. */
if(pktIteratorWriteStream(iterator, 0))
if(pktIteratorWriteStreamBit(iterator, 0))
return true;
}
/* Get data bit and advance index. */
uint8_t byte = iterator->data_buff[iterator->inp_index >> 3];
uint8_t bit = (byte >> (iterator->inp_index++ % 8)) & 0x1;
if((iterator->inp_index % 8) == 0)
iterator->data_size--;
/* Write data bit to stream. */
if(pktIteratorWriteStreamBit(iterator, bit))
return true;
} while((iterator->inp_index % 8) != 0);
/* End of input byte. */
return false;
}
@ -126,13 +166,14 @@ static bool pktEncodeFrameData(tx_iterator_t *iterator) {
*
* @param[in] iterator pointer to an @p iterator object.
* @param[in] stream pointer to buffer to write stream data.
* @param[in] qty the requested number of stream bytes.
* @param[in] qty the requested quantity of stream bytes.
* requesting 0 will return the stream bytes remaining.
*
* @return number of bytes encoded.
* @return number of bytes encoded or remaining to be encoded.
* @retval zero indicates the iterator is not initialized or is finished.
* @retval requested size is returned while encoding continues.
* @retval less than requested size is returned when encoding is ending.
* @retval number of bytes remaining to be encoded for quantity zero request.
*
* @api
*/
@ -147,14 +188,18 @@ uint16_t pktStreamEncodingIterator(tx_iterator_t *iterator,
iterator->no_write = true;
/* Count the number of bytes remaining to output to the stream. */
uint16_t remain = pktStreamEncodingIterator(iterator, NULL, 0xFFFF);
uint16_t remain = pktStreamEncodingIterator(iterator, NULL,
ITERATOR_MAX_QTY);
/* Restore state. */
*iterator = saved;
return remain;
}
/* Each call has a new quantity and buffer which starts from index 0. */
/*
* Each call specifies a quantity and stream buffer.
* The stream data is written from index 0 of the buffer.
*/
iterator->out_count = 0;
iterator->qty = qty;
iterator->out_index = 0;
@ -177,11 +222,12 @@ uint16_t pktStreamEncodingIterator(tx_iterator_t *iterator,
* Output preamble bytes of specified quantity in requested chunk size.
* RLL encoding is not used as these are HDLC flags.
*/
while(iterator->hdlc_count-- > 0) {
while(iterator->hdlc_count > 0) {
if(pktEncodeFrameHDLC(iterator))
/* True means the requested count has been reached. */
return iterator->qty;
} /* End while. */
iterator->inp_index = 0;
iterator->state = ITERATE_FRAME;
continue;
} /* End case ITERATE_PREAMBLE. */
@ -190,7 +236,7 @@ uint16_t pktStreamEncodingIterator(tx_iterator_t *iterator,
/*
* Output frame data bytes in requested chunk size.
*/
while(iterator->data_size-- > 0) {
while(iterator->data_size > 0) {
/* Consume bytes until count reached. */
if(pktEncodeFrameData(iterator))
/* True means the requested count has been reached. */
@ -208,7 +254,7 @@ uint16_t pktStreamEncodingIterator(tx_iterator_t *iterator,
/*
* Output frame CRC bytes in requested chunk size.
*/
while(iterator->data_size-- > 0) {
while(iterator->data_size > 0) {
/* Consume bytes until count reached. */
if(pktEncodeFrameData(iterator))
/* True means the requested count has been reached. */
@ -216,9 +262,8 @@ uint16_t pktStreamEncodingIterator(tx_iterator_t *iterator,
}
/* Frame CRC consumed. */
iterator->state = ITERATE_CLOSE;
iterator->hdlc_count = 10;
iterator->hdlc_count = iterator->hdlc_post;
iterator->hdlc_code = HDLC_FLAG;
iterator->hdlc_bit = 0;
iterator->inp_index = 0;
continue;
} /* End case ITERATE_CRC. */
@ -228,15 +273,16 @@ uint16_t pktStreamEncodingIterator(tx_iterator_t *iterator,
* Output closing flags.
* RLL encoding is not used as these are HDLC flags.
*/
while(iterator->hdlc_count-- > 0) {
while(iterator->hdlc_count > 0) {
if(pktEncodeFrameHDLC(iterator))
/* True means the requested count has been reached. */
return iterator->qty;
} /* End while. */
iterator->state = ITERATE_TAIL;
/* Tail length. */
iterator->hdlc_count = 10;
iterator->hdlc_count = iterator->hdlc_tail;
iterator->hdlc_code = HDLC_ZERO;
iterator->inp_index = 0;
continue;
} /* End case ITERATE_CLOSE. */
@ -246,23 +292,26 @@ uint16_t pktStreamEncodingIterator(tx_iterator_t *iterator,
* RLL encoding is not used as these are idle flags.
* This keeps the data tail clean for the receiver.
*/
while(iterator->hdlc_count-- > 0) {
while(iterator->hdlc_count > 0) {
if(pktEncodeFrameHDLC(iterator))
/* True means the requested count has been reached. */
return iterator->qty;
} /* End while. */
/* Account for RLL inserted bits. */
iterator->hdlc_count = ((iterator->rll_count + 7) / 8);
iterator->state = ITERATE_FINAL;
continue;
} /* End case ITERATE_TAIL. */
} /* End case ITERATE_TAIL. */
case ITERATE_FINAL: {
iterator->state = ITERATE_END;
/* Check for extra bits due to RLL. */
/* TODO: Calculate if RLL bits > 7 and feed out in QTY chunks. */
if((iterator->out_index % 8) != 0)
iterator->out_count++;
return iterator->out_count;
} /* End case ITERATE_FINAL. */
if(iterator->hdlc_count <= iterator->qty) {
iterator->state = ITERATE_END;
return (iterator->out_count + iterator->hdlc_count);
} else {
iterator->hdlc_count -= iterator->qty;
return iterator->qty;
}
} /* End case ITERATE_FINAL. */
} /* End switch on state. */
} /* End while. */
} /* End function. */

Wyświetl plik

@ -18,7 +18,17 @@
#ifndef PKT_PROTOCOLS_TXHDLC_H_
#define PKT_PROTOCOLS_TXHDLC_H_
#define HDLC_RLL_SEQUENCE 0x1FU
/*===========================================================================*/
/* Module constants. */
/*===========================================================================*/
#define HDLC_RLL_SEQUENCE 0x1FU
#define ITERATOR_MAX_QTY 0xFFFF
/*===========================================================================*/
/* Module data structures and types. */
/*===========================================================================*/
typedef enum {
ITERATE_INIT,
@ -33,23 +43,24 @@ typedef enum {
typedef struct {
txit_state_t state;
bool no_write;
uint16_t qty;
uint16_t out_count;
int16_t hdlc_count;
uint8_t *data_buff;
int16_t data_size;
uint8_t *out_buff;
uint8_t hdlc_code;
uint8_t crc[sizeof(uint16_t)];
uint8_t nrzi_hist;
uint8_t hdlc_hist;
uint32_t inp_index;
uint32_t out_index;
uint8_t hdlc_bit;
uint16_t rll_count;
bool scramble;
uint32_t lfsr;
bool no_write;
uint16_t qty;
uint16_t out_count;
uint8_t hdlc_count;
uint8_t hdlc_post;
uint8_t hdlc_tail;
uint8_t *data_buff;
uint16_t data_size;
uint8_t *out_buff;
uint8_t hdlc_code;
uint8_t crc[sizeof(uint16_t)];
uint8_t nrzi_hist;
uint8_t hdlc_hist;
uint32_t inp_index;
uint32_t out_index;
uint8_t rll_count;
bool scramble;
uint32_t lfsr;
} tx_iterator_t;
/*===========================================================================*/
@ -62,7 +73,11 @@ extern "C" {
uint16_t pktStreamEncodingIterator(tx_iterator_t *iterator,
uint8_t *stream, uint16_t qty);
void pktStreamIteratorInit(tx_iterator_t *iterator,
packet_t pp, bool scramble);
packet_t pp,
uint8_t pre,
uint8_t post,
uint8_t tail,
bool scramble);
#ifdef __cplusplus
}
#endif