kopia lustrzana https://github.com/DL7AD/pecanpico10
WIP FSK TX and revised AFSK TX.
rodzic
404d3497c3
commit
9dddaf105d
|
|
@ -175,6 +175,7 @@ CSRC = $(STARTUPSRC) \
|
|||
pkt/devices/dbguart.c \
|
||||
pkt/sys/ihex_out.c \
|
||||
pkt/diagnostics/ax25_dump.c \
|
||||
pkt/diagnostics/pktevt.c \
|
||||
pkt/protocols/txhdlc.c \
|
||||
\
|
||||
main.c \
|
||||
|
|
|
|||
|
|
@ -23,13 +23,11 @@ int main(void) {
|
|||
/* Start serial channels. */
|
||||
pktSerialStart();
|
||||
|
||||
event_listener_t pkt_el;
|
||||
|
||||
/* Create packet radio service. */
|
||||
if(!pktServiceCreate(PKT_RADIO_1)) {
|
||||
TRACE_ERROR("PKT > Unable to create packet services");
|
||||
} else {
|
||||
chEvtRegister(pktGetEventSource(&RPKTD1), &pkt_el, 1);
|
||||
pktEnableEventTrace();
|
||||
}
|
||||
|
||||
#if ACTIVATE_USB
|
||||
|
|
@ -44,40 +42,7 @@ int main(void) {
|
|||
#if ACTIVATE_USB
|
||||
if(isUSBactive()) {
|
||||
manageShell();
|
||||
eventmask_t evt = chEvtGetAndClearEvents(EVENT_MASK(1));
|
||||
if(evt) {
|
||||
eventflags_t flags = chEvtGetAndClearFlags(&pkt_el);
|
||||
if(flags & EVT_PWM_QUEUE_FULL) {
|
||||
TRACE_WARN("PKT > PWM queue full");
|
||||
}
|
||||
if(flags & EVT_PWM_FIFO_EMPTY) {
|
||||
TRACE_WARN("PKT > PWM FIFO exhausted");
|
||||
}
|
||||
if(flags & EVT_AX25_NO_BUFFER) {
|
||||
TRACE_WARN("PKT > AX25 FIFO exhausted");
|
||||
}
|
||||
if(flags & EVT_ICU_SLEEP_TIMEOUT) {
|
||||
TRACE_INFO("PKT > PWM ICU has entered sleep");
|
||||
}
|
||||
if(flags & EVT_AX25_BUFFER_FULL) {
|
||||
TRACE_WARN("PKT > AX25 receive buffer full");
|
||||
}
|
||||
if(flags & EVT_DECODER_ERROR) {
|
||||
TRACE_ERROR("PKT > Decoder error");
|
||||
}
|
||||
if(flags & EVT_PWM_UNKNOWN_INBAND) {
|
||||
TRACE_ERROR("PKT > Unknown PWM inband flag");
|
||||
}
|
||||
if(flags & EVT_ICU_OVERFLOW) {
|
||||
TRACE_WARN("PKT > PWM ICU overflow");
|
||||
}
|
||||
if(flags & EVT_PWM_STREAM_TIMEOUT) {
|
||||
TRACE_WARN("PKT > PWM steam timeout");
|
||||
}
|
||||
if(flags & EVT_PWM_NO_DATA) {
|
||||
TRACE_WARN("PKT > PWM data not started from radio");
|
||||
}
|
||||
}
|
||||
pktTraceEvents();
|
||||
continue;
|
||||
}
|
||||
#endif /* ACTIVATE_USB */
|
||||
|
|
|
|||
|
|
@ -1098,6 +1098,23 @@ static uint8_t Si446x_getUpsampledAFSKbits(uint8_t* buf/*, uint32_t blen*/)
|
|||
return b;
|
||||
}
|
||||
|
||||
static void Si446x_upsampleAFSKstream(uint8_t current_byte,
|
||||
uint8_t *buf,
|
||||
uint8_t upsample_rate) {
|
||||
uint8_t b = 0, i = 0, usr = 0;
|
||||
for(usr = 0; usr < upsample_rate; usr++) {
|
||||
do {
|
||||
// Toggle tone (1200 <> 2200)
|
||||
phase_delta = (current_byte & 1) ? PHASE_DELTA_1200 : PHASE_DELTA_2200;
|
||||
/* 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;
|
||||
buf[usr] = b;
|
||||
}
|
||||
}
|
||||
|
||||
#define SI446X_EVT_AFSK_TX_TIMEOUT EVENT_MASK(0)
|
||||
|
||||
static void Si446x_AFSKtransmitTimeoutI(thread_t *tp) {
|
||||
|
|
@ -1240,7 +1257,7 @@ THD_FUNCTION(si_fifo_feeder_afsk, arg) {
|
|||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* AFSK transmit manager thread.
|
||||
*/
|
||||
THD_FUNCTION(new_si_fifo_feeder_afsk, arg) {
|
||||
packet_t pp = arg;
|
||||
|
|
@ -1255,27 +1272,17 @@ THD_FUNCTION(new_si_fifo_feeder_afsk, arg) {
|
|||
|
||||
chVTObjectInit(&send_timer);
|
||||
|
||||
uint8_t layer0[AFSK_FEEDER_BUFFER_SIZE];
|
||||
//uint8_t layer0[AFSK_FEEDER_BUFFER_SIZE];
|
||||
|
||||
TRACE_INFO("SI > Packet frame bytes %i", pp->frame_len);
|
||||
|
||||
/* TODO: Make this a prepare function.
|
||||
* Create iterator object and complete TX frame.
|
||||
* Insert CRC in radio.c transmit function?
|
||||
*/
|
||||
|
||||
static tx_iterator_t iterator;
|
||||
|
||||
pktStreamIteratorInit(&iterator, pp, false);
|
||||
|
||||
static int32_t data = 0;
|
||||
data = pktStreamEncodingIterator(&iterator, layer0, sizeof(layer0));
|
||||
uint16_t all = pktStreamEncodingIterator(&iterator, NULL, 0);
|
||||
|
||||
TRACE_INFO("SI > Iterator data count %i, RLL count %i,"
|
||||
" out index %i, out bytes %i, out bits %i",
|
||||
data, iterator.rll_count,
|
||||
iterator.out_index, iterator.out_index >> 3,
|
||||
iterator.out_index % 8);
|
||||
TRACE_INFO("SI > Packet stream bytes %i", all);
|
||||
|
||||
#ifdef TX_ITERATOR_VERIFICATION
|
||||
uint8_t layer1[AFSK_FEEDER_BUFFER_SIZE];
|
||||
|
|
@ -1304,45 +1311,13 @@ THD_FUNCTION(new_si_fifo_feeder_afsk, arg) {
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Reset TX FIFO in case some remnant unsent data is left there. */
|
||||
const uint8_t reset_fifo[] = {0x15, 0x01};
|
||||
Si446x_write(reset_fifo, 2);
|
||||
|
||||
/* 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 chunk size for stream iterator. */
|
||||
|
||||
uint8_t stream_size = free / SAMPLES_PER_BAUD;
|
||||
|
||||
/* Allocate a stream output buffer. */
|
||||
uint8_t stream_out[stream_size];
|
||||
|
||||
TRACE_INFO("SI > AFSK stream buffer %i @ 0x%x", stream_size, stream_out);
|
||||
/*
|
||||
* Account for all modulation bits (round up to a byte boundary).
|
||||
* Calculate initial FIFO fill.
|
||||
*/
|
||||
uint16_t all = data * SAMPLES_PER_BAUD;
|
||||
uint16_t c = 0; /*(all > free) ? free : all;*/
|
||||
|
||||
TRACE_INFO("SI > AFSK frame bytes to send %i, upsampled %i", data, all);
|
||||
TRACE_INFO("SI > AFSK frame bytes to send %i, upsampled %i",
|
||||
all, all * SAMPLES_PER_BAUD);
|
||||
|
||||
/*
|
||||
* Start transmission timeout timer.
|
||||
* If the 446x gets locked up we'll exit TX and release packet object.
|
||||
* Initialize variables for up sampler.
|
||||
* TODO: Use an up-sampler object.
|
||||
*/
|
||||
chVTSet(&send_timer, TIME_S2I(10),
|
||||
(vtfunc_t)Si446x_AFSKtransmitTimeoutI, chThdGetSelfX());
|
||||
|
||||
/* The exit message if all goes well. */
|
||||
msg_t exit_msg = MSG_OK;
|
||||
bool tx_started = false;
|
||||
|
||||
/* Initialize variables for up sampler. */
|
||||
phase_delta = PHASE_DELTA_1200;
|
||||
phase = 0;
|
||||
packet_pos = 0;
|
||||
|
|
@ -1351,48 +1326,83 @@ THD_FUNCTION(new_si_fifo_feeder_afsk, arg) {
|
|||
|
||||
uint8_t lower = Si446x_FIFO_COMBINED_SIZE;
|
||||
|
||||
/* Feed the FIFO while data remains to be sent. */
|
||||
while((all - c) > 0) {
|
||||
/* Get TX FIFO free count. */
|
||||
uint8_t more = Si446x_getTXfreeFIFO();
|
||||
/* 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);
|
||||
|
||||
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) {
|
||||
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;
|
||||
uint16_t count = 0;
|
||||
while(iterator.state != ITERATE_END) {
|
||||
data = pktStreamEncodingIterator(&iterator, byte, IT_BYTES);
|
||||
|
||||
/* If there is more free than we need for send use remainder only. */
|
||||
more = (more > (all - c)) ? (all - c) : more;
|
||||
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));
|
||||
}
|
||||
break;
|
||||
#if 0
|
||||
if((data = pktStreamEncodingIterator(&iterator, byte, 1)) == 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
|
||||
|
||||
/* 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;
|
||||
TRACE_INFO("SI > Transmit AFSK stream byte with FIFO %i", more);
|
||||
|
||||
if(!tx_started) {
|
||||
/* Request start of transmission. */
|
||||
if(!Si446x_transmit(pp->radio_chan, pp->radio_pwr, all,
|
||||
pp->cca_rssi, TIME_S2I(10))) {
|
||||
/* Transmit start failed. */
|
||||
TRACE_ERROR("SI > Transmit start failed");
|
||||
exit_msg = MSG_RESET;
|
||||
break;
|
||||
} /* Else. */
|
||||
tx_started = true;
|
||||
}
|
||||
/*
|
||||
* Wait for 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 go back and load more data to FIFO.
|
||||
*/
|
||||
eventmask_t evt = chEvtWaitAnyTimeout(SI446X_EVT_AFSK_TX_TIMEOUT,
|
||||
chTimeUS2I(833 * 8 * SAMPLES_PER_BAUD));
|
||||
if(evt) {
|
||||
/* Force 446x out of TX state. */
|
||||
Si446x_setReadyState();
|
||||
exit_msg = MSG_TIMEOUT;
|
||||
break;
|
||||
tx_started = true;
|
||||
}
|
||||
#endif
|
||||
} /* End while. */
|
||||
/* Arrive here on break from while or TX timeout. */
|
||||
if(exit_msg != MSG_OK) {
|
||||
/* Force 446x out of TX state. */
|
||||
Si446x_setReadyState();
|
||||
}
|
||||
chVTReset(&send_timer);
|
||||
|
||||
/*
|
||||
|
|
@ -1408,7 +1418,7 @@ THD_FUNCTION(new_si_fifo_feeder_afsk, arg) {
|
|||
// Free packet object memory
|
||||
pktReleaseSendObject(pp);
|
||||
|
||||
TRACE_INFO("SI > TX FIFO low level %i", lower);
|
||||
TRACE_INFO("SI > TX FIFO lowest level %i", lower);
|
||||
|
||||
/* Exit thread. */
|
||||
chThdExit(exit_msg);
|
||||
|
|
@ -1439,10 +1449,14 @@ 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
|
||||
"446x_afsk_tx",
|
||||
NORMALPRIO - 10,
|
||||
si_fifo_feeder_afsk,
|
||||
new_si_fifo_feeder_afsk,
|
||||
pp);
|
||||
#else
|
||||
// Start/re-start FIFO feeder
|
||||
|
|
@ -1467,7 +1481,7 @@ void Si446x_sendAFSK(packet_t pp,
|
|||
TRACE_ERROR("SI > Transmit AFSK timeout");
|
||||
}
|
||||
if(send_msg == MSG_RESET) {
|
||||
TRACE_ERROR("SI > Transmit AFSK buffer overrun");
|
||||
TRACE_ERROR("SI > Transmit AFSK failed to start");
|
||||
}
|
||||
/* Unlock radio. */
|
||||
Si446x_unlockRadio(RADIO_TX);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
Aerospace Decoder - Copyright (C) 2018 Bob Anderson (VK2GJ)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include "pktconf.h"
|
||||
|
||||
event_listener_t pkt_el;
|
||||
static bool trace_enabled = false;
|
||||
|
||||
|
||||
void pktEnableEventTrace() {
|
||||
chEvtRegister(pktGetEventSource(&RPKTD1), &pkt_el, 1);
|
||||
trace_enabled = true;
|
||||
}
|
||||
|
||||
void pktDisableEventTrace() {
|
||||
trace_enabled = false;
|
||||
chEvtUnregister(pktGetEventSource(&RPKTD1), &pkt_el);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Refactor and add severity categories filtering
|
||||
*/
|
||||
void pktTraceEvents() {
|
||||
if(!trace_enabled)
|
||||
return;
|
||||
eventmask_t evt = chEvtGetAndClearEvents(EVENT_MASK(1));
|
||||
if(evt) {
|
||||
eventflags_t flags = chEvtGetAndClearFlags(&pkt_el);
|
||||
if(flags & EVT_PWM_QUEUE_FULL) {
|
||||
TRACE_WARN("PKT > PWM queue full");
|
||||
}
|
||||
if(flags & EVT_PWM_FIFO_EMPTY) {
|
||||
TRACE_WARN("PKT > PWM FIFO exhausted");
|
||||
}
|
||||
if(flags & EVT_AX25_NO_BUFFER) {
|
||||
TRACE_WARN("PKT > AX25 FIFO exhausted");
|
||||
}
|
||||
if(flags & EVT_ICU_SLEEP_TIMEOUT) {
|
||||
TRACE_INFO("PKT > PWM ICU has entered sleep");
|
||||
}
|
||||
if(flags & EVT_AX25_BUFFER_FULL) {
|
||||
TRACE_WARN("PKT > AX25 receive buffer full");
|
||||
}
|
||||
if(flags & EVT_DECODER_ERROR) {
|
||||
TRACE_ERROR("PKT > Decoder error");
|
||||
}
|
||||
if(flags & EVT_PWM_UNKNOWN_INBAND) {
|
||||
TRACE_ERROR("PKT > Unknown PWM inband flag");
|
||||
}
|
||||
if(flags & EVT_ICU_OVERFLOW) {
|
||||
TRACE_WARN("PKT > PWM ICU overflow");
|
||||
}
|
||||
if(flags & EVT_PWM_STREAM_TIMEOUT) {
|
||||
TRACE_WARN("PKT > PWM steam timeout");
|
||||
}
|
||||
if(flags & EVT_PWM_NO_DATA) {
|
||||
TRACE_WARN("PKT > PWM data not started from radio");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
Aerospace Decoder - Copyright (C) 2018 Bob Anderson (VK2GJ)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#ifndef PKT_DIAGNOSTICS_PKTEVT_H_
|
||||
#define PKT_DIAGNOSTICS_PKTEVT_H_
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void pktTraceEvents(void);
|
||||
void pktEnableEventTrace(void);
|
||||
void pktDisableEventTrace(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PKT_DIAGNOSTICS_PKTEVT_H_ */
|
||||
|
|
@ -157,8 +157,11 @@
|
|||
#include "ihex_out.h"
|
||||
#include "ax25_dump.h"
|
||||
#include "si446x.h"
|
||||
#include "pktevt.h"
|
||||
|
||||
|
||||
#ifndef PKT_IS_TEST_PROJECT
|
||||
#include "debug.h"
|
||||
#endif
|
||||
extern packet_svc_t RPKTD1;
|
||||
|
||||
/*===========================================================================*/
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ void pktStreamIteratorInit(tx_iterator_t *iterator,
|
|||
uint16_t crc = calc_crc16(pp->frame_data, 0, pp->frame_len);
|
||||
iterator->crc[0] = crc & 0xFF;
|
||||
iterator->crc[1] = crc >> 8;
|
||||
iterator->no_write = false;
|
||||
iterator->state = ITERATE_PREAMBLE;
|
||||
}
|
||||
|
||||
|
|
@ -33,8 +34,8 @@ void pktStreamIteratorInit(tx_iterator_t *iterator,
|
|||
*
|
||||
*/
|
||||
static bool pktIteratorWriteStream(tx_iterator_t *iterator, uint8_t bit) {
|
||||
/* If new byte clear it first. */
|
||||
if(iterator->out_index % 8 == 0)
|
||||
/* 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. */
|
||||
|
|
@ -55,14 +56,18 @@ static bool pktIteratorWriteStream(tx_iterator_t *iterator, uint8_t bit) {
|
|||
iterator->nrzi_hist ^= (bit == 0) ? 0x1 : 0x0;
|
||||
|
||||
/* Write NRZI bit to current byte. */
|
||||
iterator->out_buff[iterator->out_index >> 3] |=
|
||||
(iterator->nrzi_hist & 0x1) << (iterator->out_index % 8);
|
||||
if(iterator->no_write == false)
|
||||
iterator->out_buff[iterator->out_index >> 3] |=
|
||||
(iterator->nrzi_hist & 0x1) << (iterator->out_index % 8);
|
||||
|
||||
/* If byte was completed and required quantity reached, return true. */
|
||||
if((++iterator->out_index % 8) == 0)
|
||||
return (++iterator->out_count == iterator->qty);
|
||||
else
|
||||
return false;
|
||||
/* If byte was completed check quantity status. */
|
||||
if((iterator->inp_index % 8) == 0) {
|
||||
if((++iterator->out_count) == iterator->qty) {
|
||||
//iterator->out_index = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -70,10 +75,14 @@ static bool pktIteratorWriteStream(tx_iterator_t *iterator, uint8_t bit) {
|
|||
*/
|
||||
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)))
|
||||
return true;
|
||||
<< (iterator->out_index % 8))) {
|
||||
if(iterator->hdlc_bit == 8)
|
||||
iterator->hdlc_bit = 0;
|
||||
return true;
|
||||
}
|
||||
} while(iterator->hdlc_bit < 8);
|
||||
iterator->hdlc_bit = 0;
|
||||
return false;
|
||||
|
|
@ -86,27 +95,21 @@ static bool pktEncodeFrameHDLC(tx_iterator_t *iterator) {
|
|||
static bool pktEncodeFrameData(tx_iterator_t *iterator) {
|
||||
do {
|
||||
|
||||
/*
|
||||
* RLL encoding is enabled for the packet data pay load.
|
||||
* Except the last data byte which is the HDLC flag.
|
||||
*/
|
||||
if((iterator->hdlc_hist & HDLC_RLL_SEQUENCE) == HDLC_RLL_SEQUENCE) {
|
||||
iterator->rll_count++;
|
||||
/* Insert RLL 0 to HDLC output stream. */
|
||||
if(pktIteratorWriteStream(iterator, 0)) {
|
||||
//if(++iterator->out_count == iterator->qty)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/* 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)) {
|
||||
//if(++iterator->out_count == iterator->qty)
|
||||
if(pktIteratorWriteStream(iterator, bit))
|
||||
return true;
|
||||
|
||||
/* RLL encoding is enabled 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))
|
||||
return true;
|
||||
}
|
||||
} while((iterator->inp_index % 8) != 0);
|
||||
return false;
|
||||
|
|
@ -118,10 +121,13 @@ static bool pktEncodeFrameData(tx_iterator_t *iterator) {
|
|||
* @post When the stream is complete the iterator may be re-used.
|
||||
* @notes The iterator allows a frame to be encoded in chunks.
|
||||
* @notes The calling function may request chunk sizes from 1 byte up.
|
||||
* @notes A quantity of 0 will return the number of bytes pending only.
|
||||
* @notes In this case no data is actually written to the stream.
|
||||
*
|
||||
* @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.
|
||||
* requesting 0 will return the stream bytes remaining.
|
||||
*
|
||||
* @return number of bytes encoded.
|
||||
* @retval zero indicates the iterator is not initialized or is finished.
|
||||
|
|
@ -131,22 +137,39 @@ static bool pktEncodeFrameData(tx_iterator_t *iterator) {
|
|||
* @api
|
||||
*/
|
||||
uint16_t pktStreamEncodingIterator(tx_iterator_t *iterator,
|
||||
uint8_t *stream, size_t qty) {
|
||||
uint8_t *stream, uint16_t qty) {
|
||||
|
||||
if(qty == 0)
|
||||
return 0;
|
||||
if(qty == 0) {
|
||||
tx_iterator_t saved;
|
||||
|
||||
/* Save state. */
|
||||
saved = *iterator;
|
||||
iterator->no_write = true;
|
||||
|
||||
/* Count the number of bytes remaining to output to the stream. */
|
||||
uint16_t remain = pktStreamEncodingIterator(iterator, NULL, 0xFFFF);
|
||||
|
||||
/* Restore state. */
|
||||
*iterator = saved;
|
||||
return remain;
|
||||
}
|
||||
|
||||
/* Each call has a new quantity and buffer which starts from index 0. */
|
||||
iterator->out_count = 0;
|
||||
iterator->qty = qty;
|
||||
iterator->out_index = 0;
|
||||
|
||||
chDbgAssert(stream != NULL, "no stream buffer allocated");
|
||||
chDbgAssert((stream != NULL) || (iterator->no_write == true),
|
||||
"no stream buffer allocated");
|
||||
|
||||
iterator->out_buff = stream;
|
||||
|
||||
while(true) {
|
||||
switch(iterator->state) {
|
||||
case ITERATE_INIT:
|
||||
case ITERATE_FINAL:
|
||||
return 0;
|
||||
|
||||
case ITERATE_END:
|
||||
return 0;
|
||||
|
||||
case ITERATE_PREAMBLE: {
|
||||
|
|
@ -160,7 +183,7 @@ uint16_t pktStreamEncodingIterator(tx_iterator_t *iterator,
|
|||
return iterator->qty;
|
||||
} /* End while. */
|
||||
iterator->state = ITERATE_FRAME;
|
||||
break;
|
||||
continue;
|
||||
} /* End case ITERATE_PREAMBLE. */
|
||||
|
||||
case ITERATE_FRAME: {
|
||||
|
|
@ -173,12 +196,12 @@ uint16_t pktStreamEncodingIterator(tx_iterator_t *iterator,
|
|||
/* True means the requested count has been reached. */
|
||||
return iterator->qty;
|
||||
}
|
||||
/* All frame data input consumed. */
|
||||
/* All frame data input consumed. Switch to CRC fields. */
|
||||
iterator->state = ITERATE_CRC;
|
||||
iterator->data_buff = iterator->crc;
|
||||
iterator->data_size = sizeof(iterator->crc);
|
||||
iterator->inp_index = 0;
|
||||
break;
|
||||
continue;
|
||||
} /* End case ITERATE_FRAME. */
|
||||
|
||||
case ITERATE_CRC: {
|
||||
|
|
@ -196,7 +219,8 @@ uint16_t pktStreamEncodingIterator(tx_iterator_t *iterator,
|
|||
iterator->hdlc_count = 10;
|
||||
iterator->hdlc_code = HDLC_FLAG;
|
||||
iterator->hdlc_bit = 0;
|
||||
break;
|
||||
iterator->inp_index = 0;
|
||||
continue;
|
||||
} /* End case ITERATE_CRC. */
|
||||
|
||||
case ITERATE_CLOSE: {
|
||||
|
|
@ -213,6 +237,7 @@ uint16_t pktStreamEncodingIterator(tx_iterator_t *iterator,
|
|||
/* Tail length. */
|
||||
iterator->hdlc_count = 10;
|
||||
iterator->hdlc_code = HDLC_ZERO;
|
||||
continue;
|
||||
} /* End case ITERATE_CLOSE. */
|
||||
|
||||
case ITERATE_TAIL: {
|
||||
|
|
@ -227,11 +252,17 @@ uint16_t pktStreamEncodingIterator(tx_iterator_t *iterator,
|
|||
return iterator->qty;
|
||||
} /* End while. */
|
||||
iterator->state = ITERATE_FINAL;
|
||||
/* Round up to include any partial bits in next byte. */
|
||||
if(iterator->out_index % 8 != 0)
|
||||
++iterator->out_count;
|
||||
return (iterator->out_count);
|
||||
continue;
|
||||
} /* 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. */
|
||||
} /* End switch on state. */
|
||||
} /* End while. */
|
||||
} /* End function. */
|
||||
|
|
|
|||
|
|
@ -27,11 +27,13 @@ typedef enum {
|
|||
ITERATE_CRC,
|
||||
ITERATE_CLOSE,
|
||||
ITERATE_TAIL,
|
||||
ITERATE_FINAL
|
||||
ITERATE_FINAL,
|
||||
ITERATE_END
|
||||
} txit_state_t;
|
||||
|
||||
typedef struct {
|
||||
txit_state_t state;
|
||||
bool no_write;
|
||||
uint16_t qty;
|
||||
uint16_t out_count;
|
||||
int16_t hdlc_count;
|
||||
|
|
@ -58,7 +60,7 @@ typedef struct {
|
|||
extern "C" {
|
||||
#endif
|
||||
uint16_t pktStreamEncodingIterator(tx_iterator_t *iterator,
|
||||
uint8_t *stream, size_t qty);
|
||||
uint8_t *stream, uint16_t qty);
|
||||
void pktStreamIteratorInit(tx_iterator_t *iterator,
|
||||
packet_t pp, bool scramble);
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
Ładowanie…
Reference in New Issue