34 #ifdef __PROPELLER_COG__
42 #ifndef __PROPELLER_COG__
52 this->set_data_width(UART::DEFAULT_DATA_WIDTH);
53 this->set_parity(UART::DEFAULT_PARITY);
54 this->set_stop_bit_width(UART::DEFAULT_STOP_BIT_WIDTH);
55 this->set_baud_rate(_cfg_baudrate);
56 this->set_rx_mask((
Port::Mask) (1 << _cfg_rxpin));
66 this->set_data_width(UART::DEFAULT_DATA_WIDTH);
67 this->set_parity(UART::DEFAULT_PARITY);
68 this->set_stop_bit_width(UART::DEFAULT_STOP_BIT_WIDTH);
69 this->set_baud_rate(_cfg_baudrate);
70 this->set_rx_mask(rx);
80 return this->m_pin.get_mask();
83 virtual ErrorCode set_data_width (
const uint8_t dataWidth) {
85 check_errors(UART::set_data_width(dataWidth));
88 this->set_receivable_bits();
94 UART::set_parity(parity);
96 this->set_receivable_bits();
105 uint32_t rxVal = this->shift_in_data(this->m_receivableBits, this->m_bitCycles, this->m_pin.get_mask(),
108 if (
static_cast<bool>(this->m_parity) && this->check_parity(rxVal))
109 return static_cast<uint32_t
>(-1);
111 return rxVal & this->m_dataMask;
121 PropWare::ErrorCode
receive (uint32_t &data)
const {
122 const uint32_t rxVal = this->shift_in_data(this->m_receivableBits, this->m_bitCycles,
123 this->m_pin.get_mask(), this->m_msbMask);
125 if (
static_cast<bool>(this->m_parity) && this->check_parity(rxVal))
128 data = rxVal & this->m_dataMask;
147 const uint32_t rxVal = this->shift_in_data(this->m_receivableBits, this->m_bitCycles,
148 this->m_pin.get_mask(), this->m_msbMask,
timeout);
149 if (
static_cast<uint32_t
>(-1) == rxVal)
151 else if (
static_cast<bool>(this->m_parity) && this->check_parity(rxVal))
154 data = rxVal & this->m_dataMask;
175 PropWare::ErrorCode
get_line (
char *buffer, int32_t *length,
const char delimiter =
'\n')
const {
178 else if (0 == *length)
183 if (8 >= this->m_receivableBits) {
185 __asm__
volatile (
"andn dira, %0" : :
"r" (this->m_pin.get_mask()));
187 *length = this->shift_in_byte_array((uint32_t) buffer, *length, delimiter);
190 for (int32_t i = 0; i < *length; --i)
191 if (this->check_parity(
static_cast<uint32_t
>(buffer[i])))
201 if (
static_cast<uint32_t
>(-1) == rxVal)
204 *buffer = (
char) rxVal;
208 }
while (rxVal != delimiter && wordCnt < *length);
225 PropWare::ErrorCode
receive_array (uint8_t *buffer, uint32_t length)
const {
226 PropWare::ErrorCode err;
229 if (8 >= this->m_receivableBits) {
231 __asm__
volatile (
"andn dira, %0" : :
"r" (this->m_pin.get_mask()));
233 this->shift_in_byte_array(buffer, length);
236 for (uint32_t i = 0; i < length; --i)
237 check_errors(this->check_parity(buffer[i]));
243 for (uint32_t i = 0; i < length; ++i) {
244 if (
static_cast<uint32_t
>(-1) == (temp = this->
receive()))
247 buffer[i] = (
char) temp;
265 PropWare::ErrorCode err;
268 if (8 >= this->m_receivableBits) {
270 __asm__
volatile (
"andn dira, %0" : :
"r" (this->m_pin.get_mask()));
272 if (!this->shift_in_byte_array(buffer, length,
timeout))
275 for (uint32_t i = 0; i < length; --i)
276 check_errors(this->check_parity(buffer[i]));
282 for (uint32_t i = 0; i < length; ++i) {
284 buffer[i] =
static_cast<uint8_t
>(rxVal);
302 PropWare::ErrorCode
fgets (
char string[], int32_t *bufferSize)
const {
303 const int32_t originalBufferSize = *bufferSize;
305 PropWare::ErrorCode err;
306 check_errors(this->
get_line(
string, bufferSize));
309 if (*bufferSize != originalBufferSize ||
'\n' ==
string[originalBufferSize])
310 string[*bufferSize - 1] =
'\0';
323 void set_msb_mask () {
324 if (
static_cast<bool>(this->m_parity))
325 this->m_msbMask = (
Port::Mask) (1 << this->m_dataWidth);
327 this->m_msbMask = (
Port::Mask) (1 << (this->m_dataWidth - 1));
334 void set_receivable_bits () {
335 if (
static_cast<bool>(this->m_parity))
336 this->m_receivableBits = (uint8_t) (this->m_dataWidth + 1);
338 this->m_receivableBits = this->m_dataWidth;
344 uint32_t shift_in_data (uint_fast8_t bits,
const uint32_t bitCycles,
const register uint32_t rxMask,
345 const uint32_t msbMask)
const {
346 volatile uint32_t data = 0;
347 volatile uint32_t waitCycles = bitCycles;
349 #ifndef DOXYGEN_IGNORE
351 FC_START(
"ShiftInDataStart%=",
"ShiftInDataEnd%=")
352 " shr %[_waitCycles], #1 \n\t"
353 " add %[_waitCycles], %[_bitCycles] \n\t"
354 " waitpne %[_rxMask], %[_rxMask] \n\t"
355 " add %[_waitCycles], CNT \n\t"
359 " waitcnt %[_waitCycles], %[_bitCycles] \n\t"
360 " shr %[_data],# 1 \n\t"
361 " test %[_rxMask],ina wz \n\t"
362 " muxnz %[_data], %[_msbMask] \n\t"
363 " djnz %[_bits], #" FC_ADDR(
"loop%=",
"ShiftInDataStart%=")
" \n\t"
366 " waitpeq %[_rxMask], %[_rxMask] \n\t"
367 FC_END(
"ShiftInDataEnd%=")
370 [_waitCycles]
"+r"(waitCycles),
373 [_rxMask]
"r"(rxMask),
374 [_msbMask]
"r"(msbMask),
375 [_bitCycles]
"r"(bitCycles));
384 uint32_t shift_in_data (uint_fast8_t bits,
const uint32_t bitCycles,
const uint32_t rxMask,
385 const uint32_t msbMask, uint32_t timeoutCycles)
const {
386 volatile uint32_t data = -1;
387 volatile uint32_t waitCycles = bitCycles;
391 #ifndef DOXYGEN_IGNORE
393 FC_START(
"ShiftInDataStart%=",
"ShiftInDataEnd%=")
394 " shr %[_waitCycles], #1 \n\t"
395 " add %[_waitCycles], %[_bitCycles] \n\t"
398 " test %[_rxMask], ina wz \n\t"
399 " if_nz djnz %[_timeout], #" FC_ADDR(
"awaitStart%=",
"ShiftInDataStart%=")
" \n\t"
400 " add %[_waitCycles], CNT \n\t"
401 " if_nz jmp #" FC_ADDR(
"end%=",
"ShiftInDataStart%=")
" \n\t"
405 " waitcnt %[_waitCycles], %[_bitCycles] \n\t"
406 " shr %[_data],# 1 \n\t"
407 " test %[_rxMask],ina wz \n\t"
408 " muxnz %[_data], %[_msbMask] \n\t"
409 " djnz %[_bits], #" FC_ADDR(
"loop%=",
"ShiftInDataStart%=")
" \n\t"
412 " waitpeq %[_rxMask], %[_rxMask] \n\t"
414 FC_END(
"ShiftInDataEnd%=")
417 [_waitCycles]
"+r"(waitCycles),
419 [_timeout]
"+r"(timeoutCycles)
421 [_rxMask]
"r"(rxMask),
422 [_msbMask]
"r"(msbMask),
423 [_bitCycles]
"r"(bitCycles));
436 int shift_in_byte_array (uint32_t bufferAddr,
const int maxLength,
const char delimiter)
const {
437 volatile uint32_t data = 0;
438 volatile int wordCnt = 0;
439 volatile uint32_t bitIdx = 0;
440 volatile uint32_t waitCycles = 0;
441 volatile uint32_t initWaitCycles = (this->m_bitCycles >> 1) + this->m_bitCycles;
443 #ifndef DOXYGEN_IGNORE
446 FC_START(
"ShiftInStringStart%=",
"ShiftInStringEnd%=")
449 " mov %[_bitIdx], %[_bits] \n\t"
451 " mov %[_waitCycles], %[_initWaitCycles] \n\t"
453 " waitpne %[_rxMask], %[_rxMask] \n\t"
455 " add %[_waitCycles], CNT \n\t"
459 " waitcnt %[_waitCycles], %[_bitCycles] \n\t"
460 " shr %[_data], #1 \n\t"
461 " test %[_rxMask], ina wz \n\t"
462 " muxnz %[_data], %[_msbMask] \n\t"
463 " djnz %[_bitIdx], #" FC_ADDR(
"innerLoop%=",
"ShiftInStringStart%=")
" \n\t"
466 " wrbyte %[_data], %[_bufAdr] \n\t"
469 " and %[_data], #0xff \n\t"
470 " cmp %[_data], %[_delim] wz \n\t"
473 " mov %[_data], #0 \n\t"
475 " add %[_wordCnt], #1 \n\t"
476 " add %[_bufAdr], #1 \n\t"
479 " cmp %[_wordCnt], %[_maxLength] wc \n\t"
482 " waitpeq %[_rxMask], %[_rxMask] \n\t"
486 "if_nz_and_c jmp #" FC_ADDR(
"outerLoop%=",
"ShiftInStringStart%=")
" \n\t"
487 FC_END(
"ShiftInStringEnd%=")
489 [_bitIdx]
"+r"(bitIdx),
490 [_waitCycles]
"+r"(waitCycles),
492 [_bufAdr]
"+r"(bufferAddr),
493 [_wordCnt]
"+r"(wordCnt)
495 [_rxMask]
"r"(this->m_pin.get_mask()),
496 [_bits]
"r"(this->m_receivableBits),
497 [_bitCycles]
"r"(this->m_bitCycles),
498 [_initWaitCycles]
"r"(initWaitCycles),
499 [_msbMask]
"r"(this->m_msbMask),
500 [_delim]
"r"(delimiter),
501 [_maxLength]
"r"(maxLength));
513 void shift_in_byte_array (uint8_t *buffer,
unsigned int length)
const {
514 uint32_t initWaitCycles = (this->m_bitCycles >> 1) + this->m_bitCycles;
516 #ifndef DOXYGEN_IGNORE
519 #define ASMVAR(name) FC_ADDR(#name "%=", "ShiftInArrayDataStart%=")
520 FC_START(
"ShiftInArrayDataStart%=",
"ShiftInArrayDataEnd%=")
521 " jmp #" FC_ADDR(
"outerLoop%=",
"ShiftInArrayDataStart%=")
" \n\t"
530 " mov " ASMVAR(data)
", #0 \n\t"
534 " mov " ASMVAR(bitIdx)
", %[_bits] \n\t"
536 " mov " ASMVAR(waitCycles)
", %[_initWaitCycles] \n\t"
538 " waitpne %[_rxMask], %[_rxMask] \n\t"
540 " add " ASMVAR(waitCycles)
", CNT \n\t"
544 " waitcnt " ASMVAR(waitCycles)
", %[_bitCycles] \n\t"
545 " shr " ASMVAR(data)
", #1 \n\t"
546 " test %[_rxMask], ina wz \n\t"
547 " muxnz " ASMVAR(data)
", %[_msbMask] \n\t"
548 " djnz " ASMVAR(bitIdx)
", #" FC_ADDR(
"innerLoop%=",
"ShiftInArrayDataStart%=")
" \n\t"
551 " wrbyte " ASMVAR(data)
", %[_bufAdr] \n\t"
554 " mov " ASMVAR(data)
", #0 \n\t"
556 " add %[_bufAdr], #1 \n\t"
559 " waitpeq %[_rxMask], %[_rxMask] \n\t"
560 " djnz %[_length], #" FC_ADDR(
"outerLoop%=",
"ShiftInArrayDataStart%=")
" \n\t"
561 FC_END(
"ShiftInArrayDataEnd%=")
564 [_bufAdr]
"+r"(buffer),
565 [_length]
"+r"(length)
567 [_rxMask]
"r"(this->m_pin.get_mask()),
568 [_bits]
"r"(this->m_receivableBits),
569 [_bitCycles]
"r"(this->m_bitCycles),
570 [_initWaitCycles]
"r"(initWaitCycles),
571 [_msbMask]
"r"(this->m_msbMask));
586 bool shift_in_byte_array (uint8_t *buffer,
unsigned int length, uint32_t
timeout)
const {
587 uint32_t initWaitCycles = (this->m_bitCycles >> 1) + this->m_bitCycles;
588 volatile uint32_t timeLeft = 0;
592 #ifndef DOXYGEN_IGNORE
595 #define ASMVAR(name) FC_ADDR(#name "%=", "ShiftInArrayDataStart%=")
596 FC_START(
"ShiftInArrayDataStart%=",
"ShiftInArrayDataEnd%=")
597 " jmp #" FC_ADDR(
"outerLoop%=",
"ShiftInArrayDataStart%=")
" \n\t"
606 " mov " ASMVAR(data)
", #0 \n\t"
610 " mov " ASMVAR(bitIdx)
", %[_bits] \n\t"
612 " mov " ASMVAR(waitCycles)
", %[_initWaitCycles] \n\t"
615 " mov %[_timeLeft], %[_timeout] \n\t"
617 " test %[_rxMask], ina wz \n\t"
618 " if_nz djnz %[_timeLeft], #" FC_ADDR(
"awaitStart%=",
"ShiftInArrayDataStart%=")
" \n\t"
620 " add " ASMVAR(waitCycles)
", CNT \n\t"
622 " if_nz jmp #" FC_ADDR(
"end%=",
"ShiftInArrayDataStart%=")
" \n\t"
626 " waitcnt " ASMVAR(waitCycles)
", %[_bitCycles] \n\t"
627 " shr " ASMVAR(data)
", #1 \n\t"
628 " test %[_rxMask], ina wz \n\t"
629 " muxnz " ASMVAR(data)
", %[_msbMask] \n\t"
630 " djnz " ASMVAR(bitIdx)
", #" FC_ADDR(
"innerLoop%=",
"ShiftInArrayDataStart%=")
" \n\t"
633 " wrbyte " ASMVAR(data)
", %[_bufAdr] \n\t"
636 " mov " ASMVAR(data)
", #0 \n\t"
638 " add %[_bufAdr], #1 \n\t"
641 " waitpeq %[_rxMask], %[_rxMask] \n\t"
642 " djnz %[_length], #" FC_ADDR(
"outerLoop%=",
"ShiftInArrayDataStart%=")
" \n\t"
645 FC_END(
"ShiftInArrayDataEnd%=")
648 [_bufAdr]
"+r"(buffer),
649 [_length]
"+r"(length),
650 [_timeLeft]
"+r"(timeLeft)
652 [_rxMask]
"r"(this->m_pin.get_mask()),
653 [_bits]
"r"(this->m_receivableBits),
654 [_bitCycles]
"r"(this->m_bitCycles),
655 [_initWaitCycles]
"r"(initWaitCycles),
656 [_msbMask]
"r"(this->m_msbMask),
660 return 0 != timeLeft;
672 PropWare::ErrorCode check_parity (uint32_t rxVal)
const {
673 uint32_t evenParityResult;
675 evenParityResult = 0;
676 __asm__
volatile(
"test %[_data], %[_dataMask] wc \n\t"
677 "muxc %[_parityResult], %[_parityMask]"
678 : [_parityResult]
"+r"(evenParityResult)
679 : [_data]
"r"(rxVal),
680 [_dataMask]
"r"(this->m_dataMask),
681 [_parityMask]
"r"(this->m_parityMask));
685 if (evenParityResult == (rxVal & this->m_parityMask))
687 }
else if (evenParityResult != (rxVal & this->m_parityMask))
697 uint8_t m_receivableBits;
700 #ifdef __PROPELLER_COG__