49 return this->m_rx.get_mask();
57 this->set_receivable_bits();
65 this->set_receivable_bits();
70 uint32_t wideDataMask = this->m_dataMask;
74 rxVal = this->shift_in_data(this->m_receivableBits, this->m_bitCycles, this->m_rx.get_mask(),
77 if (this->m_parity && 0 != this->check_parity(rxVal))
80 return rxVal & wideDataMask;
86 else if (0 == *length)
91 if (8 >= this->m_receivableBits) {
93 __asm__
volatile (
"andn dira, %0" : :
"r" (this->m_rx.get_mask()));
95 *length = this->shift_in_byte_array((uint32_t) buffer, *length, delimiter);
98 for (int32_t i = 0; i < *length; --i)
99 if (0 != this->check_parity((uint32_t) buffer[i]))
108 if (((uint32_t) -1) == (temp = this->
receive()))
111 *buffer = (char) temp;
114 }
while (temp != delimiter && wordCnt < *length);
124 if (8 >= this->m_receivableBits) {
126 __asm__
volatile (
"andn dira, %0" : :
"r" (this->m_rx.get_mask()));
128 this->shift_in_byte_array(buffer, length);
131 for (uint32_t i = 0; i < length; --i)
132 if (0 != this->check_parity((uint32_t) buffer[i]))
139 for (uint32_t i = 0; i < length; ++i) {
140 if (((uint32_t) -1) == (temp = this->
receive()))
142 buffer[i] = (char) temp;
160 PropWare::ErrorCode
fgets (
char string[], int32_t *bufferSize)
const {
161 const int32_t originalBufferSize = *bufferSize;
163 PropWare::ErrorCode err;
164 check_errors(this->
get_line(
string, bufferSize));
167 if (*bufferSize != originalBufferSize ||
'\n' ==
string[originalBufferSize])
168 string[*bufferSize - 1] =
'\0';
207 void set_msb_mask () {
209 this->m_msbMask = (
Port::Mask) (1 << this->m_dataWidth);
211 this->m_msbMask = (
Port::Mask) (1 << (this->m_dataWidth - 1));
218 void set_receivable_bits () {
220 this->m_receivableBits = (uint8_t) (this->m_dataWidth + 1);
222 this->m_receivableBits = this->m_dataWidth;
228 uint32_t shift_in_data (uint_fast8_t bits,
const uint32_t bitCycles,
const register uint32_t rxMask,
229 const uint32_t msbMask)
const {
230 volatile uint32_t data = 0;
231 volatile uint32_t waitCycles = bitCycles;
233 #ifndef DOXYGEN_IGNORE 235 FC_START(
"ShiftInDataStart",
"ShiftInDataEnd")
236 " shr %[_waitCycles], #1 \n\t" 237 " add %[_waitCycles], %[_bitCycles] \n\t" 238 " waitpne %[_rxMask], %[_rxMask] \n\t" 239 " add %[_waitCycles], CNT \n\t" 243 " waitcnt %[_waitCycles], %[_bitCycles] \n\t" 244 " shr %[_data],# 1 \n\t" 245 " test %[_rxMask],ina wz \n\t" 246 " muxnz %[_data], %[_msbMask] \n\t" 247 " djnz %[_bits], #" FC_ADDR(
"loop%=",
"ShiftInDataStart")
" \n\t" 250 " waitpeq %[_rxMask], %[_rxMask] \n\t" 251 FC_END(
"ShiftInDataEnd")
254 [_waitCycles]
"+r"(waitCycles),
257 [_rxMask]
"r"(rxMask),
258 [_msbMask]
"r"(msbMask),
259 [_bitCycles]
"r"(bitCycles));
272 int shift_in_byte_array (uint32_t bufferAddr,
const int maxLength,
const char delimiter)
const {
273 volatile uint32_t data = 0;
274 volatile int wordCnt = 0;
275 volatile uint32_t bitIdx = 0;
276 volatile uint32_t waitCycles = 0;
277 volatile uint32_t initWaitCycles = (this->m_bitCycles >> 1) + this->m_bitCycles;
279 #ifndef DOXYGEN_IGNORE 282 FC_START(
"ShiftInStringStart",
"ShiftInStringEnd")
285 " mov %[_bitIdx], %[_bits] \n\t" 287 " mov %[_waitCycles], %[_initWaitCycles] \n\t" 289 " waitpne %[_rxMask], %[_rxMask] \n\t" 291 " add %[_waitCycles], CNT \n\t" 295 " waitcnt %[_waitCycles], %[_bitCycles] \n\t" 296 " shr %[_data], #1 \n\t" 297 " test %[_rxMask], ina wz \n\t" 298 " muxnz %[_data], %[_msbMask] \n\t" 299 " djnz %[_bitIdx], #" FC_ADDR(
"innerLoop%=",
"ShiftInStringStart")
" \n\t" 302 " wrbyte %[_data], %[_bufAdr] \n\t" 305 " and %[_data], #0xff \n\t" 306 " cmp %[_data], %[_delim] wz \n\t" 309 " mov %[_data], #0 \n\t" 311 " add %[_wordCnt], #1 \n\t" 312 " add %[_bufAdr], #1 \n\t" 315 " cmp %[_wordCnt], %[_maxLength] wc \n\t" 318 " waitpeq %[_rxMask], %[_rxMask] \n\t" 322 "if_nz_and_c jmp #" FC_ADDR(
"outerLoop%=",
"ShiftInStringStart")
" \n\t" 323 FC_END(
"ShiftInStringEnd")
325 [_bitIdx]
"+r"(bitIdx),
326 [_waitCycles]
"+r"(waitCycles),
328 [_bufAdr]
"+r"(bufferAddr),
329 [_wordCnt]
"+r"(wordCnt)
331 [_rxMask]
"r"(this->m_rx.get_mask()),
332 [_bits]
"r"(this->m_receivableBits),
333 [_bitCycles]
"r"(this->m_bitCycles),
334 [_initWaitCycles]
"r"(initWaitCycles),
335 [_msbMask]
"r"(this->m_msbMask),
336 [_delim]
"r"(delimiter),
337 [_maxLength]
"r"(maxLength));
349 void shift_in_byte_array (uint8_t *buffer,
unsigned int length)
const {
350 uint32_t initWaitCycles = (this->m_bitCycles >> 1) + this->m_bitCycles;
352 #ifndef DOXYGEN_IGNORE 355 #define ASMVAR(name) FC_ADDR(#name "%=", "ShiftInArrayDataStart") 356 FC_START(
"ShiftInArrayDataStart",
"ShiftInArrayDataEnd")
357 " jmp #" FC_ADDR(
"outerLoop%=",
"ShiftInArrayDataStart")
" \n\t" 366 " mov " ASMVAR(data)
", #0 \n\t" 370 " mov " ASMVAR(bitIdx)
", %[_bits] \n\t" 372 " mov " ASMVAR(waitCycles)
", %[_initWaitCycles] \n\t" 374 " waitpne %[_rxMask], %[_rxMask] \n\t" 376 " add " ASMVAR(waitCycles)
", CNT \n\t" 380 " waitcnt " ASMVAR(waitCycles)
", %[_bitCycles] \n\t" 381 " shr " ASMVAR(data)
", #1 \n\t" 382 " test %[_rxMask], ina wz \n\t" 383 " muxnz " ASMVAR(data)
", %[_msbMask] \n\t" 384 " djnz " ASMVAR(bitIdx)
", #" FC_ADDR(
"innerLoop%=",
"ShiftInArrayDataStart")
" \n\t" 387 " wrbyte " ASMVAR(data)
", %[_bufAdr] \n\t" 390 " mov " ASMVAR(data)
", #0 \n\t" 392 " add %[_bufAdr], #1 \n\t" 395 " waitpeq %[_rxMask], %[_rxMask] \n\t" 396 " djnz %[_length], #" FC_ADDR(
"outerLoop%=",
"ShiftInArrayDataStart")
" \n\t" 397 FC_END(
"ShiftInArrayDataEnd")
400 [_bufAdr]
"+r"(buffer),
401 [_length]
"+r"(length)
403 [_rxMask]
"r"(this->m_rx.get_mask()),
404 [_bits]
"r"(this->m_receivableBits),
405 [_bitCycles]
"r"(this->m_bitCycles),
406 [_initWaitCycles]
"r"(initWaitCycles),
407 [_msbMask]
"r"(this->m_msbMask));
419 ErrorCode check_parity (uint32_t rxVal)
const {
420 uint32_t evenParityResult;
421 uint32_t wideParityMask = this->m_parityMask;
422 uint32_t wideDataMask = this->m_dataMask;
424 evenParityResult = 0;
425 __asm__
volatile(
"test %[_data], %[_dataMask] wc \n\t" 426 "muxc %[_parityResult], %[_parityMask]" 427 : [_parityResult]
"+r"(evenParityResult)
428 : [_data]
"r"(rxVal),
429 [_dataMask]
"r"(wideDataMask),
430 [_parityMask]
"r"(wideParityMask));
433 if (evenParityResult != (rxVal & this->m_parityMask))
435 }
else if (evenParityResult == (rxVal & this->m_parityMask))
444 uint8_t m_receivableBits;
void set_mask(const PropWare::Port::Mask mask)
Utility class to handle general purpose I/O pins.
virtual ErrorCode set_data_width(const uint8_t dataWidth)
Set the number of bits for each word of data.
void set_dir(const PropWare::Port::Dir direction) const
Set port as either input or output.
virtual ErrorCode set_data_width(const uint8_t dataWidth)
Set the number of bits for each word of data.
void set_dir_in() const
Set the port for input.
Generic definitions and functions for the Parallax Propeller.
Interface for all duplex UART devices.
void set_tx_mask(const Port::Mask tx)
Set the pin mask for TX pin.
PropWare::ErrorCode fgets(char string[], int32_t *bufferSize) const
Read words from the bus until a newline character (\\n) is received or the buffer is filled...
void set_baud_rate(const int32_t baudRate)
Set the baud rate.
Port::Mask get_rx_mask() const
Retrieve the currently configured receive (RX) pin mask.
A base class for any non-buffered UART that is capable of both transmitting and receiving.
virtual void set_parity(const UART::Parity parity)
Set the parity configuration.
ErrorCode set_stop_bit_width(const uint8_t stopBitWidth)
Set the number of stop bits used.
Abstract base class for all unbuffered UART devices.
virtual void set_parity(const UART::Parity parity)
Set the parity configuration.
void set_rx_mask(const Port::Mask rx)
Set the pin mask for RX pin.
ErrorCode receive_array(uint8_t *buffer, uint32_t length) const
Receive an array of data words.
ErrorCode get_line(char *buffer, int32_t *length, const uint32_t delimiter= '\n') const
Receive an array of data words.
uint32_t receive() const
Receive one word of data; Will block until word is received.