@@ -43,28 +43,21 @@ void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint
43
43
44
44
if ( mode == UART_INT_CLOCK )
45
45
{
46
- uint16_t sampleRateValue ;
46
+ uint16_t sampleRateValue;
47
47
48
- if ( sampleRate == SAMPLE_RATE_x16 )
49
- {
50
- sampleRateValue = 16 ;
51
- }
52
- else
53
- {
54
- if ( sampleRate == SAMPLE_RATE_x8 )
55
- {
56
- sampleRateValue = 8 ;
57
- }
58
- else
59
- {
60
- sampleRateValue = 3 ;
61
- }
48
+ if (sampleRate == SAMPLE_RATE_x16) {
49
+ sampleRateValue = 16 ;
50
+ } else {
51
+ sampleRateValue = 8 ;
62
52
}
63
53
64
- // Asynchronous arithmetic mode
65
- // 65535 * ( 1 - sampleRateValue * baudrate / SystemCoreClock);
66
- // 65535 - 65535 * (sampleRateValue * baudrate / SystemCoreClock));
67
- sercom->USART .BAUD .reg = 65535 .0f * ( 1 .0f - (float )(sampleRateValue) * (float )(baudrate) / (float )(SystemCoreClock));
54
+ // Asynchronous fractional mode (Table 24-2 in datasheet)
55
+ // BAUD = fref / (sampleRateValue * fbaud)
56
+ // (multiply by 8, to calculate fractional piece)
57
+ uint32_t baudTimes8 = (SystemCoreClock * 8 ) / (sampleRateValue * baudrate);
58
+
59
+ sercom->USART .BAUD .FRAC .FP = (baudTimes8 % 8 );
60
+ sercom->USART .BAUD .FRAC .BAUD = (baudTimes8 / 8 );
68
61
}
69
62
}
70
63
void SERCOM::initFrame (SercomUartCharSize charSize, SercomDataOrder dataOrder, SercomParityMode parityMode, SercomNumberStopBit nbStopBits)
@@ -112,7 +105,7 @@ void SERCOM::enableUART()
112
105
void SERCOM::flushUART ()
113
106
{
114
107
// Wait for transmission to complete
115
- while (sercom->USART .INTFLAG .bit .DRE != SERCOM_USART_INTFLAG_DRE );
108
+ while (! sercom->USART .INTFLAG .bit .TXC );
116
109
}
117
110
118
111
void SERCOM::clearStatusUART ()
@@ -168,8 +161,8 @@ uint8_t SERCOM::readDataUART()
168
161
169
162
int SERCOM::writeDataUART (uint8_t data)
170
163
{
171
- // Flush UART buffer
172
- flushUART ( );
164
+ // Wait for data register to be empty
165
+ while (! isDataRegisterEmptyUART () );
173
166
174
167
// Put data into DATA register
175
168
sercom->USART .DATA .reg = (uint16_t )data;
@@ -262,6 +255,11 @@ void SERCOM::setDataOrderSPI(SercomDataOrder dataOrder)
262
255
enableSPI ();
263
256
}
264
257
258
+ SercomDataOrder SERCOM::getDataOrderSPI ()
259
+ {
260
+ return (sercom->SPI .CTRLA .bit .DORD ? LSB_FIRST : MSB_FIRST);
261
+ }
262
+
265
263
void SERCOM::setBaudrateSPI (uint8_t divider)
266
264
{
267
265
// Can't divide by 0
@@ -410,14 +408,12 @@ void SERCOM::initSlaveWIRE( uint8_t ucAddress )
410
408
// Set slave mode
411
409
sercom->I2CS .CTRLA .bit .MODE = I2C_SLAVE_OPERATION ;
412
410
413
- // Enable Quick Command
414
- sercom->I2CM .CTRLB .bit .QCEN = 1 ;
415
-
416
411
sercom->I2CS .ADDR .reg = SERCOM_I2CS_ADDR_ADDR ( ucAddress & 0x7Ful ) | // 0x7F, select only 7 bits
417
- SERCOM_I2CS_ADDR_ADDRMASK ( 0x3FFul ) ; // 0x3FF all bits set
412
+ SERCOM_I2CS_ADDR_ADDRMASK ( 0x00ul ) ; // 0x00, only match exact address
418
413
419
414
// Set the interrupt register
420
- sercom->I2CS .INTENSET .reg = SERCOM_I2CS_INTENSET_AMATCH | // Address Match
415
+ sercom->I2CS .INTENSET .reg = SERCOM_I2CS_INTENSET_PREC | // Stop
416
+ SERCOM_I2CS_INTENSET_AMATCH | // Address Match
421
417
SERCOM_I2CS_INTENSET_DRDY ; // Data Ready
422
418
423
419
while ( sercom->I2CM .SYNCBUSY .bit .SYSOP != 0 )
@@ -450,23 +446,35 @@ void SERCOM::initMasterWIRE( uint32_t baudrate )
450
446
451
447
void SERCOM::prepareNackBitWIRE ( void )
452
448
{
453
- // Send a NACK
454
- sercom->I2CM .CTRLB .bit .ACKACT = 1 ;
449
+ if (isMasterWIRE ()) {
450
+ // Send a NACK
451
+ sercom->I2CM .CTRLB .bit .ACKACT = 1 ;
452
+ } else {
453
+ sercom->I2CS .CTRLB .bit .ACKACT = 1 ;
454
+ }
455
455
}
456
456
457
457
void SERCOM::prepareAckBitWIRE ( void )
458
458
{
459
- // Send an ACK
460
- sercom->I2CM .CTRLB .bit .ACKACT = 0 ;
459
+ if (isMasterWIRE ()) {
460
+ // Send an ACK
461
+ sercom->I2CM .CTRLB .bit .ACKACT = 0 ;
462
+ } else {
463
+ sercom->I2CS .CTRLB .bit .ACKACT = 0 ;
464
+ }
461
465
}
462
466
463
- void SERCOM::prepareCommandBitsWire (SercomMasterCommandWire cmd)
467
+ void SERCOM::prepareCommandBitsWire (uint8_t cmd)
464
468
{
465
- sercom->I2CM .CTRLB .bit .CMD = cmd;
469
+ if (isMasterWIRE ()) {
470
+ sercom->I2CM .CTRLB .bit .CMD = cmd;
466
471
467
- while (sercom->I2CM .SYNCBUSY .bit .SYSOP )
468
- {
469
- // Waiting for synchronization
472
+ while (sercom->I2CM .SYNCBUSY .bit .SYSOP )
473
+ {
474
+ // Waiting for synchronization
475
+ }
476
+ } else {
477
+ sercom->I2CS .CTRLB .bit .CMD = cmd;
470
478
}
471
479
}
472
480
@@ -475,8 +483,8 @@ bool SERCOM::startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag
475
483
// 7-bits address + 1-bits R/W
476
484
address = (address << 0x1ul ) | flag;
477
485
478
- // Wait idle bus mode
479
- while ( !isBusIdleWIRE () );
486
+ // Wait idle or owner bus mode
487
+ while ( !isBusIdleWIRE () && ! isBusOwnerWIRE () );
480
488
481
489
// Send start and address
482
490
sercom->I2CM .ADDR .bit .ADDR = address;
@@ -570,6 +578,11 @@ bool SERCOM::isBusIdleWIRE( void )
570
578
return sercom->I2CM .STATUS .bit .BUSSTATE == WIRE_IDLE_STATE;
571
579
}
572
580
581
+ bool SERCOM::isBusOwnerWIRE ( void )
582
+ {
583
+ return sercom->I2CM .STATUS .bit .BUSSTATE == WIRE_OWNER_STATE;
584
+ }
585
+
573
586
bool SERCOM::isDataReadyWIRE ( void )
574
587
{
575
588
return sercom->I2CS .INTFLAG .bit .DRDY ;
0 commit comments