kopia lustrzana https://github.com/DL7AD/pecanpico10
TX iterator now implemented in AFSK TX. FSK TX WIP.
rodzic
393a1d59b5
commit
9fccfd3271
|
|
@ -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 "${INPUTS}"" 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 "${INPUTS}"" prefer-non-shared="true">
|
||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
||||
</provider>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Ładowanie…
Reference in New Issue