94 return this->m_tx.get_mask();
98 if (1 > dataWidth || dataWidth > 16)
101 this->m_dataWidth = dataWidth;
103 this->m_dataMask = 0;
104 for (uint8_t i = 0; i < this->m_dataWidth; ++i)
105 this->m_dataMask |= 1 << i;
107 this->set_parity_mask();
108 this->set_total_bits();
114 return this->m_dataWidth;
118 this->m_parity = parity;
119 this->set_parity_mask();
120 this->set_stop_bit_mask();
121 this->set_total_bits();
125 return this->m_parity;
130 if (0 == stopBitWidth || stopBitWidth > 14)
133 this->m_stopBitWidth = stopBitWidth;
135 this->set_stop_bit_mask();
137 this->set_total_bits();
143 return this->m_stopBitWidth;
147 this->m_bitCycles = CLKFREQ / baudRate;
151 return CLKFREQ / this->m_bitCycles;
154 virtual void send (uint16_t originalData)
const {
155 uint32_t wideData = originalData;
163 __asm__
volatile(
"test %[_data], %[_dataMask] wc \n\t" 164 "muxc %[_data], %[_parityMask]" 165 : [_data]
"+r"(wideData)
166 : [_dataMask]
"r"(this->m_dataMask),
167 [_parityMask]
"r"(this->m_parityMask));
169 __asm__
volatile(
"test %[_data], %[_dataMask] wc \n\t" 170 "muxnc %[_data], %[_parityMask]" 171 : [_data]
"+r"(wideData)
172 : [_dataMask]
"r"(this->m_dataMask),
173 [_parityMask]
"r"(this->m_parityMask));
177 wideData |= this->m_stopBitMask;
182 this->shift_out_data(wideData, this->m_totalBits, this->m_bitCycles, this->m_tx.get_mask());
185 virtual void send_array (
const char array[], uint32_t words)
const {
186 char *arrayPtr = (
char *) array;
187 uint32_t data = 0, waitCycles = 0, bits = 0;
193 #ifndef DOXYGEN_IGNORE 194 switch (this->m_parity) {
197 FC_START(
"SendArrayStart%=",
"SendArrayEnd%=")
199 "sendArrayLoop%=: \n\t" 200 " rdbyte %[_data], %[_arrayPtr] \n\t" 202 " or %[_data], %[_stopBitMask] \n\t" 203 " shl %[_data], #1 \n\t" 206 " mov %[_bits], %[_totalBits] \n\t" 207 " mov %[_waitCycles], %[_bitCycles] \n\t" 208 " add %[_waitCycles], CNT \n\t" 209 "sendWordLoop%=: \n\t" 210 " waitcnt %[_waitCycles], %[_bitCycles] \n\t" 211 " shr %[_data],#1 wc \n\t" 212 " muxc outa, %[_mask] \n\t" 213 " djnz %[_bits], #" FC_ADDR(
"sendWordLoop%=",
"SendArrayStart%=")
" \n\t" 216 " add %[_arrayPtr], #1 \n\t" 217 " djnz %[_words], #" FC_ADDR(
"sendArrayLoop%=",
"SendArrayStart%=")
" \n\t" 218 FC_END(
"SendArrayEnd%=")
219 : [_data]
"+r"(data),
220 [_waitCycles]
"+r"(waitCycles),
221 [_arrayPtr]
"+r"(arrayPtr),
224 : [_mask]
"r"(this->m_tx.get_mask()),
225 [_bitCycles]
"r"(this->m_bitCycles),
226 [_totalBits]
"r"(this->m_totalBits),
227 [_stopBitMask]
"r"(this->m_stopBitMask));
231 FC_START(
"SendArrayStart%=",
"SendArrayEnd%=")
234 " rdbyte %[_data], %[_arrayPtr] \n\t" 236 " test %[_data], %[_dataMask] wc \n\t" 237 " muxnc %[_data], %[_parityMask] \n\t" 239 " or %[_data], %[_stopBitMask] \n\t" 240 " shl %[_data], #1 \n\t" 243 " mov %[_bits], %[_totalBits] \n\t" 244 " mov %[_waitCycles], %[_bitCycles] \n\t" 245 " add %[_waitCycles], CNT \n\t" 246 "sendWordLoop%=: \n\t" 247 " waitcnt %[_waitCycles], %[_bitCycles] \n\t" 248 " shr %[_data],#1 wc \n\t" 249 " muxc outa, %[_mask] \n\t" 250 " djnz %[_bits], #" FC_ADDR(
"sendWordLoop%=",
"SendArrayStart%=")
" \n\t" 253 " add %[_arrayPtr], #1 \n\t" 254 " djnz %[_words], #" FC_ADDR(
"sendArrayLoop%=",
"SendArrayStart%=")
" \n\t" 255 FC_END(
"SendArrayEnd%=")
256 : [_data]
"+r"(data),
257 [_waitCycles]
"+r"(waitCycles),
258 [_arrayPtr]
"+r"(arrayPtr),
261 : [_mask]
"r"(this->m_tx.get_mask()),
262 [_bitCycles]
"r"(this->m_bitCycles),
263 [_totalBits]
"r"(this->m_totalBits),
264 [_stopBitMask]
"r"(this->m_stopBitMask),
265 [_dataMask]
"r"(this->m_dataMask),
266 [_parityMask]
"r"(this->m_parityMask));
270 FC_START(
"SendArrayStart%=",
"SendArrayEnd%=")
273 " rdbyte %[_data], %[_arrayPtr] \n\t" 275 " test %[_data], %[_dataMask] wc \n\t" 276 " muxc %[_data], %[_parityMask] \n\t" 278 " or %[_data], %[_stopBitMask] \n\t" 279 " shl %[_data], #1 \n\t" 282 " mov %[_bits], %[_totalBits] \n\t" 283 " mov %[_waitCycles], %[_bitCycles] \n\t" 284 " add %[_waitCycles], CNT \n\t" 285 "sendWordLoop%=: \n\t" 286 " waitcnt %[_waitCycles], %[_bitCycles] \n\t" 287 " shr %[_data],#1 wc \n\t" 288 " muxc outa, %[_mask] \n\t" 289 " djnz %[_bits], #" FC_ADDR(
"sendWordLoop%=",
"SendArrayStart%=")
" \n\t" 292 " add %[_arrayPtr], #1 \n\t" 293 " djnz %[_words], #" FC_ADDR(
"sendArrayLoop%=",
"SendArrayStart%=")
" \n\t" 294 FC_END(
"SendArrayEnd%=")
295 : [_data]
"+r"(data),
296 [_waitCycles]
"+r"(waitCycles),
297 [_arrayPtr]
"+r"(arrayPtr),
300 : [_mask]
"r"(this->m_tx.get_mask()),
301 [_bitCycles]
"r"(this->m_bitCycles),
302 [_totalBits]
"r"(this->m_totalBits),
303 [_stopBitMask]
"r"(this->m_stopBitMask),
304 [_dataMask]
"r"(this->m_dataMask),
305 [_parityMask]
"r"(this->m_parityMask));
312 this->
send((uint16_t) c);
315 void puts (
const char string[]) {
316 const uint32_t length = strlen(
string);
331 (
Port::Mask const) (1 << *UART::PARALLAX_STANDARD_TX));
339 void set_stop_bit_mask () {
341 this->m_stopBitMask = 1;
342 for (uint8_t i = 0; i < this->m_stopBitWidth - 1; ++i)
343 this->m_stopBitMask |= this->m_stopBitMask << 1;
347 this->m_stopBitMask <<= this->m_dataWidth;
349 this->m_stopBitMask <<= 1;
356 void set_parity_mask () {
357 this->m_parityMask = (uint16_t) (1 << this->m_dataWidth);
366 void set_total_bits () {
368 this->m_totalBits = (uint8_t) (1 + this->m_dataWidth
369 + this->m_stopBitWidth);
382 inline void shift_out_data (uint32_t data, uint32_t bits,
const uint32_t bitCycles,
383 const uint32_t txMask)
const {
384 #ifndef DOXYGEN_IGNORE 385 volatile uint32_t waitCycles = bitCycles;
387 FC_START(
"ShiftOutDataStart%=",
"ShiftOutDataEnd%=")
388 " add %[_waitCycles], CNT \n\t" 391 " waitcnt %[_waitCycles], %[_bitCycles] \n\t" 392 " shr %[_data],#1 wc \n\t" 393 " muxc outa, %[_mask] \n\t" 394 " djnz %[_bits], #" FC_ADDR(
"loop%=",
"ShiftOutDataStart%=")
" \n\t" 395 FC_END(
"ShiftOutDataEnd%=")
396 : [_data]
"+r"(data),
397 [_waitCycles]
"+r"(waitCycles),
399 : [_mask]
"r"(txMask),
400 [_bitCycles]
"r"(bitCycles));
409 uint16_t m_parityMask;
410 uint8_t m_stopBitWidth;
411 uint32_t m_stopBitMask;
412 uint32_t m_bitCycles;
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.
virtual void send_array(const char array[], uint32_t words) const
Send an array of 8-bit (or smaller) words.
void set_dir(const PropWare::Port::Dir direction) const
Set port as either input or output.
int32_t get_baud_rate() const
Retrieve the current baud rate.
uint8_t get_stop_bit_width() const
Retrieve the current number of stop bits in use.
void clear() const
Clear selected output port (set it to 0)
Generic definitions and functions for the Parallax Propeller.
UART::Parity get_parity() const
Retrieve the current parity configuration.
void puts(const char string[])
Send a null-terminated character array. Though this method could be created using put_char...
Port::Mask get_tx_mask() const
Retrieve the currently configured transmit (TX) pin mask.
Interface for all UART devices.
void set_tx_mask(const Port::Mask tx)
Set the pin mask for TX pin.
void set_dir_out() const
Set the port for output.
void set_baud_rate(const int32_t baudRate)
Set the baud rate.
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.
virtual void send(uint16_t originalData) const
Send a word of data out the serial port.
Abstract base class for all unbuffered UART devices.
void put_char(const char c)
Print a single character.
void set() const
Set selected output port high (set all pins to 1)
uint8_t get_data_width() const
Retrieve the currently configured data width.