Ignore:
Timestamp:
Mar 28, 2016, 2:09:46 PM (8 years ago)
Author:
ertl-honda
Message:

ライブラリを Arduino IDE 1.7.9 にupdate

File:
1 edited

Legend:

Unmodified
Added
Removed
  • rtos_arduino/trunk/arduino_lib/hardware/arduino/samd/cores/arduino/SERCOM.cpp

    r136 r175  
     1/*
     2  Copyright (c) 2014 Arduino.  All right reserved.
     3
     4  This library is free software; you can redistribute it and/or
     5  modify it under the terms of the GNU Lesser General Public
     6  License as published by the Free Software Foundation; either
     7  version 2.1 of the License, or (at your option) any later version.
     8
     9  This library is distributed in the hope that it will be useful,
     10  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     12  See the GNU Lesser General Public License for more details.
     13
     14  You should have received a copy of the GNU Lesser General Public
     15  License along with this library; if not, write to the Free Software
     16  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     17*/
     18
    119#include "SERCOM.h"
    220#include "variant.h"
    321
     22
    423SERCOM::SERCOM(Sercom* s)
    524{
    6         sercom = s;
     25  sercom = s;
    726}
    827
     
    1332void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate)
    1433{
     34  initClockNVIC();
    1535  resetUART();
    16   initClockNVIC();
    1736
    1837  //Setting the CTRLA register
     
    2645  if ( mode == UART_INT_CLOCK )
    2746  {
    28     uint16_t sampleRateValue ;
    29 
    30     if ( sampleRate == SAMPLE_RATE_x16 )
    31     {
    32       sampleRateValue = 16 ;
     47    uint16_t sampleRateValue;
     48
     49    if (sampleRate == SAMPLE_RATE_x16) {
     50      sampleRateValue = 16;
     51    } else {
     52      sampleRateValue = 8;
    3353    }
    34     else
    35     {
    36       if ( sampleRate == SAMPLE_RATE_x8 )
    37       {
    38         sampleRateValue = 8 ;
    39       }
    40       else
    41       {
    42         sampleRateValue = 3 ;
    43       }
    44     }
    45 
    46     // Asynchronous arithmetic mode
    47     // 65535 * ( 1 - sampleRateValue * baudrate / SystemCoreClock);
    48     // 65535 - 65535 * (sampleRateValue * baudrate / SystemCoreClock));
    49     sercom->USART.BAUD.reg = 65535.0f * ( 1.0f - (float)(sampleRateValue) * (float)(baudrate) / (float)(SystemCoreClock));
     54
     55    // Asynchronous fractional mode (Table 24-2 in datasheet)
     56    //   BAUD = fref / (sampleRateValue * fbaud)
     57    // (multiply by 8, to calculate fractional piece)
     58    uint32_t baudTimes8 = (SystemCoreClock * 8) / (sampleRateValue * baudrate);
     59
     60    sercom->USART.BAUD.FRAC.FP   = (baudTimes8 % 8);
     61    sercom->USART.BAUD.FRAC.BAUD = (baudTimes8 / 8);
    5062  }
    5163}
    5264void SERCOM::initFrame(SercomUartCharSize charSize, SercomDataOrder dataOrder, SercomParityMode parityMode, SercomNumberStopBit nbStopBits)
    5365{
    54         //Setting the CTRLA register
    55         sercom->USART.CTRLA.reg |=      SERCOM_USART_CTRLA_FORM( (parityMode == SERCOM_NO_PARITY ? 0 : 1) ) |
    56                                                                 dataOrder << SERCOM_USART_CTRLA_DORD_Pos;
    57 
    58         //Setting the CTRLB register
    59         sercom->USART.CTRLB.reg |=      SERCOM_USART_CTRLB_CHSIZE(charSize) |
    60                                                                 nbStopBits << SERCOM_USART_CTRLB_SBMODE_Pos |
    61                                                                 (parityMode == SERCOM_NO_PARITY ? 0 : parityMode) << SERCOM_USART_CTRLB_PMODE_Pos; //If no parity use default value
     66  //Setting the CTRLA register
     67  sercom->USART.CTRLA.reg |=    SERCOM_USART_CTRLA_FORM( (parityMode == SERCOM_NO_PARITY ? 0 : 1) ) |
     68                dataOrder << SERCOM_USART_CTRLA_DORD_Pos;
     69
     70  //Setting the CTRLB register
     71  sercom->USART.CTRLB.reg |=    SERCOM_USART_CTRLB_CHSIZE(charSize) |
     72                nbStopBits << SERCOM_USART_CTRLB_SBMODE_Pos |
     73                (parityMode == SERCOM_NO_PARITY ? 0 : parityMode) << SERCOM_USART_CTRLB_PMODE_Pos; //If no parity use default value
    6274}
    6375
    6476void SERCOM::initPads(SercomUartTXPad txPad, SercomRXPad rxPad)
    6577{
    66         //Setting the CTRLA register
    67         sercom->USART.CTRLA.reg |=      SERCOM_USART_CTRLA_TXPO(txPad) |
    68                                                                 SERCOM_USART_CTRLA_RXPO(rxPad);
     78  //Setting the CTRLA register
     79  sercom->USART.CTRLA.reg |=    SERCOM_USART_CTRLA_TXPO(txPad) |
     80                SERCOM_USART_CTRLA_RXPO(rxPad);
    6981
    7082  // Enable Transceiver and Receiver
     
    8597void SERCOM::enableUART()
    8698{
    87         //Setting  the enable bit to 1
    88         sercom->USART.CTRLA.bit.ENABLE = 0x1u;
    89 
    90         //Wait for then enable bit from SYNCBUSY is equal to 0;
    91         while(sercom->USART.SYNCBUSY.bit.ENABLE);
     99  //Setting  the enable bit to 1
     100  sercom->USART.CTRLA.bit.ENABLE = 0x1u;
     101
     102  //Wait for then enable bit from SYNCBUSY is equal to 0;
     103  while(sercom->USART.SYNCBUSY.bit.ENABLE);
    92104}
    93105
    94106void SERCOM::flushUART()
    95107{
    96         // Wait for transmission to complete
    97         while(sercom->USART.INTFLAG.bit.DRE != SERCOM_USART_INTFLAG_DRE);
     108  // Wait for transmission to complete
     109  while(!sercom->USART.INTFLAG.bit.TXC);
    98110}
    99111
    100112void SERCOM::clearStatusUART()
    101113{
    102         //Reset (with 0) the STATUS register
    103         sercom->USART.STATUS.reg = SERCOM_USART_STATUS_RESETVALUE;
     114  //Reset (with 0) the STATUS register
     115  sercom->USART.STATUS.reg = SERCOM_USART_STATUS_RESETVALUE;
    104116}
    105117
    106118bool SERCOM::availableDataUART()
    107119{
    108         //RXC : Receive Complete
    109         return sercom->USART.INTFLAG.bit.RXC;
     120  //RXC : Receive Complete
     121  return sercom->USART.INTFLAG.bit.RXC;
     122}
     123
     124bool SERCOM::isUARTError()
     125{
     126  return sercom->USART.INTFLAG.bit.ERROR;
     127}
     128
     129void SERCOM::acknowledgeUARTError()
     130{
     131  sercom->USART.INTFLAG.bit.ERROR = 1;
    110132}
    111133
    112134bool SERCOM::isBufferOverflowErrorUART()
    113135{
    114         //BUFOVF : Buffer Overflow
    115         return sercom->USART.STATUS.bit.BUFOVF;
     136  //BUFOVF : Buffer Overflow
     137  return sercom->USART.STATUS.bit.BUFOVF;
    116138}
    117139
    118140bool SERCOM::isFrameErrorUART()
    119141{
    120         //FERR : Frame Error
    121         return sercom->USART.STATUS.bit.FERR;
     142  //FERR : Frame Error
     143  return sercom->USART.STATUS.bit.FERR;
    122144}
    123145
    124146bool SERCOM::isParityErrorUART()
    125147{
    126         //PERR : Parity Error
    127         return sercom->USART.STATUS.bit.PERR;
     148  //PERR : Parity Error
     149  return sercom->USART.STATUS.bit.PERR;
    128150}
    129151
    130152bool SERCOM::isDataRegisterEmptyUART()
    131153{
    132         //DRE : Data Register Empty
    133         return sercom->USART.INTFLAG.bit.DRE;
     154  //DRE : Data Register Empty
     155  return sercom->USART.INTFLAG.bit.DRE;
    134156}
    135157
    136158uint8_t SERCOM::readDataUART()
    137159{
    138         return sercom->USART.DATA.bit.DATA;
     160  return sercom->USART.DATA.bit.DATA;
    139161}
    140162
    141163int SERCOM::writeDataUART(uint8_t data)
    142164{
    143         //Flush UART buffer
    144         flushUART();
    145 
    146         //Put data into DATA register
    147         sercom->USART.DATA.reg = (uint16_t)data;
    148         return 1;
     165  // Wait for data register to be empty
     166  while(!isDataRegisterEmptyUART());
     167
     168  //Put data into DATA register
     169  sercom->USART.DATA.reg = (uint16_t)data;
     170  return 1;
    149171}
    150172
     
    155177void SERCOM::initSPI(SercomSpiTXPad mosi, SercomRXPad miso, SercomSpiCharSize charSize, SercomDataOrder dataOrder)
    156178{
     179  resetSPI();
     180  initClockNVIC();
     181
     182  //Setting the CTRLA register
     183  sercom->SPI.CTRLA.reg =       SERCOM_SPI_CTRLA_MODE_SPI_MASTER |
     184                          SERCOM_SPI_CTRLA_DOPO(mosi) |
     185                          SERCOM_SPI_CTRLA_DIPO(miso) |
     186                          dataOrder << SERCOM_SPI_CTRLA_DORD_Pos;
     187
     188  //Setting the CTRLB register
     189  sercom->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(charSize) |
     190                          SERCOM_SPI_CTRLB_RXEN;        //Active the SPI receiver.
     191
     192
     193}
     194
     195void SERCOM::initSPIslave(SercomSpiTXPad mosi, SercomRXPad miso, SercomSpiCharSize charSize, SercomDataOrder dataOrder)
     196{
    157197        resetSPI();
    158198        initClockNVIC();
    159199
    160         //Setting the CTRLA register
    161         sercom->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_MODE_SPI_MASTER |
    162                                                                     SERCOM_SPI_CTRLA_DOPO(mosi) |
    163                                                                     SERCOM_SPI_CTRLA_DIPO(miso) |
    164                                                                     dataOrder << SERCOM_SPI_CTRLA_DORD_Pos;
    165 
    166         //Setting the CTRLB register
     200        sercom->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_MODE_SPI_SLAVE |
     201                                                                    SERCOM_SPI_CTRLA_DOPO(mosi) |  //provo a modificare
     202                                                                    SERCOM_SPI_CTRLA_DIPO(miso) |  //provo a modificare
     203                                                                    dataOrder << SERCOM_SPI_CTRLA_DORD_Pos;                                                 
     204
    167205        sercom->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(charSize) |
    168                                                                     SERCOM_SPI_CTRLB_RXEN;      //Active the SPI receiver.
    169 
    170 
     206                                                                    SERCOM_SPI_CTRLB_RXEN;      //Active the SPI receiver.
     207                                                                               
    171208}
    172209
    173210void SERCOM::initSPIClock(SercomSpiClockMode clockMode, uint32_t baudrate)
    174211{
    175         //Extract data from clockMode
    176         int cpha, cpol;
    177 
    178         if((clockMode & (0x1ul)) == 0 )
    179                 cpha = 0;
    180         else
    181                 cpha = 1;
    182 
    183         if((clockMode & (0x2ul)) == 0)
    184                 cpol = 0;
    185         else
    186                 cpol = 1;
    187 
    188         //Setting the CTRLA register
    189         sercom->SPI.CTRLA.reg |=        ( cpha << SERCOM_SPI_CTRLA_CPHA_Pos ) |
    190                                                                             ( cpol << SERCOM_SPI_CTRLA_CPOL_Pos );
    191 
    192         //Synchronous arithmetic
    193         sercom->SPI.BAUD.reg = calculateBaudrateSynchronous(baudrate);
     212  //Extract data from clockMode
     213  int cpha, cpol;
     214
     215  if((clockMode & (0x1ul)) == 0 )
     216    cpha = 0;
     217  else
     218    cpha = 1;
     219
     220  if((clockMode & (0x2ul)) == 0)
     221    cpol = 0;
     222  else
     223    cpol = 1;
     224
     225  //Setting the CTRLA register
     226  sercom->SPI.CTRLA.reg |=      ( cpha << SERCOM_SPI_CTRLA_CPHA_Pos ) |
     227                            ( cpol << SERCOM_SPI_CTRLA_CPOL_Pos );
     228
     229  //Synchronous arithmetic
     230  sercom->SPI.BAUD.reg = calculateBaudrateSynchronous(baudrate);
    194231}
    195232
    196233void SERCOM::resetSPI()
    197234{
    198         //Setting the Software Reset bit to 1
    199         sercom->SPI.CTRLA.bit.SWRST = 1;
    200 
    201         //Wait both bits Software Reset from CTRLA and SYNCBUSY are equal to 0
    202         while(sercom->SPI.CTRLA.bit.SWRST || sercom->SPI.SYNCBUSY.bit.SWRST);
     235  //Setting the Software Reset bit to 1
     236  sercom->SPI.CTRLA.bit.SWRST = 1;
     237
     238  //Wait both bits Software Reset from CTRLA and SYNCBUSY are equal to 0
     239  while(sercom->SPI.CTRLA.bit.SWRST || sercom->SPI.SYNCBUSY.bit.SWRST);
    203240}
    204241
    205242void SERCOM::enableSPI()
    206243{
    207         //Setting the enable bit to 1
    208         sercom->SPI.CTRLA.bit.ENABLE = 1;
    209 
    210         while(sercom->SPI.SYNCBUSY.bit.ENABLE)
     244  //Setting the enable bit to 1
     245  sercom->SPI.CTRLA.bit.ENABLE = 1;
     246
     247  while(sercom->SPI.SYNCBUSY.bit.ENABLE)
    211248  {
    212249    //Waiting then enable bit from SYNCBUSY is equal to 0;
     
    216253void SERCOM::disableSPI()
    217254{
    218         //Setting the enable bit to 0
    219         sercom->SPI.CTRLA.bit.ENABLE = 0;
    220 
    221         while(sercom->SPI.SYNCBUSY.bit.ENABLE)
     255  //Setting the enable bit to 0
     256  sercom->SPI.CTRLA.bit.ENABLE = 0;
     257
     258  while(sercom->SPI.SYNCBUSY.bit.ENABLE)
    222259  {
    223260    //Waiting then enable bit from SYNCBUSY is equal to 0;
     
    227264void SERCOM::setDataOrderSPI(SercomDataOrder dataOrder)
    228265{
    229         //Register enable-protected
    230         disableSPI();
    231 
    232         sercom->SPI.CTRLA.bit.DORD = dataOrder;
    233 
    234         enableSPI();
    235 }
    236 
    237 void SERCOM::setBaudrateSPI(uint8_t divider)
    238 {
    239         //Can't divide by 0
    240         if(divider == 0)
    241                 return;
    242 
    243         //Register enable-protected
    244         disableSPI();
    245 
    246         sercom->SPI.BAUD.reg = calculateBaudrateSynchronous( SERCOM_FREQ_REF / divider );
    247 
    248         enableSPI();
     266  //Register enable-protected
     267  disableSPI();
     268
     269  sercom->SPI.CTRLA.bit.DORD = dataOrder;
     270
     271  enableSPI();
     272}
     273
     274SercomDataOrder SERCOM::getDataOrderSPI()
     275{
     276  return (sercom->SPI.CTRLA.bit.DORD ? LSB_FIRST : MSB_FIRST);
     277}
     278
     279void SERCOM::setBaudrateSPI(uint16_t divider)
     280{
     281  //Can't divide by 0
     282  if(divider == 0)
     283    return;
     284
     285  //Register enable-protected
     286  disableSPI();
     287
     288  sercom->SPI.BAUD.reg = calculateBaudrateSynchronous( SERCOM_FREQ_REF / divider );
     289
     290  enableSPI();
    249291}
    250292
    251293void SERCOM::setClockModeSPI(SercomSpiClockMode clockMode)
    252294{
    253         int cpha, cpol;
    254         if((clockMode & (0x1ul)) == 0)
    255                 cpha = 0;
    256         else
    257                 cpha = 1;
    258 
    259         if((clockMode & (0x2ul)) == 0)
    260                 cpol = 0;
    261         else
    262                 cpol = 1;
    263 
    264         //Register enable-protected
    265         disableSPI();
    266 
    267         sercom->SPI.CTRLA.bit.CPOL = cpol;
    268         sercom->SPI.CTRLA.bit.CPHA = cpha;
    269 
    270         enableSPI();
    271 }
     295  int cpha, cpol;
     296  if((clockMode & (0x1ul)) == 0)
     297    cpha = 0;
     298  else
     299    cpha = 1;
     300
     301  if((clockMode & (0x2ul)) == 0)
     302    cpol = 0;
     303  else
     304    cpol = 1;
     305
     306  //Register enable-protected
     307  disableSPI();
     308
     309  sercom->SPI.CTRLA.bit.CPOL = cpol;
     310  sercom->SPI.CTRLA.bit.CPHA = cpha;
     311
     312  enableSPI();
     313}
     314
    272315void SERCOM::writeDataSPI(uint8_t data)
    273316{
     
    276319    // Waiting Data Registry Empty
    277320  }
    278 
    279         sercom->SPI.DATA.bit.DATA = data; // Writing data into Data register
     321  sercom->SPI.DATA.bit.DATA = data; // Writing data into Data register
    280322
    281323  while( sercom->SPI.INTFLAG.bit.TXC == 0 || sercom->SPI.INTFLAG.bit.DRE == 0 )
     
    292334  }
    293335
    294         return sercom->SPI.DATA.bit.DATA;  // Reading data
     336  return sercom->SPI.DATA.bit.DATA;  // Reading data
    295337}
    296338
    297339bool SERCOM::isBufferOverflowErrorSPI()
    298340{
    299         return sercom->SPI.STATUS.bit.BUFOVF;
     341  return sercom->SPI.STATUS.bit.BUFOVF;
    300342}
    301343
    302344bool SERCOM::isDataRegisterEmptySPI()
    303345{
    304         //DRE : Data Register Empty
    305         return sercom->SPI.INTFLAG.bit.DRE;
    306 }
     346  //DRE : Data Register Empty
     347  return sercom->SPI.INTFLAG.bit.DRE;
     348}
     349
     350//bool SERCOM::isTransmitCompleteSPI()
     351//{
     352//      //TXC : Transmit complete
     353//      return sercom->SPI.INTFLAG.bit.TXC;
     354//}
     355//
     356//bool SERCOM::isReceiveCompleteSPI()
     357//{
     358//      //RXC : Receive complete
     359//      return sercom->SPI.INTFLAG.bit.RXC;
     360//}
    307361
    308362uint8_t SERCOM::calculateBaudrateSynchronous(uint32_t baudrate)
    309363{
    310         return SERCOM_FREQ_REF / (2 * baudrate) - 1;
     364  return SERCOM_FREQ_REF / (2 * baudrate) - 1;
    311365}
    312366
     
    315369 *      ===== Sercom WIRE
    316370 *      =========================
    317 */
    318 
     371 */
    319372void SERCOM::resetWIRE()
    320373{
    321         //I2CM OR I2CS, no matter SWRST is the same bit.
    322 
    323         //Setting the Software bit to 1
    324         sercom->I2CM.CTRLA.bit.SWRST = 1;
    325 
    326         //Wait both bits Software Reset from CTRLA and SYNCBUSY are equal to 0
    327         while(sercom->I2CM.CTRLA.bit.SWRST || sercom->I2CM.SYNCBUSY.bit.SWRST);
     374  //I2CM OR I2CS, no matter SWRST is the same bit.
     375
     376  //Setting the Software bit to 1
     377  sercom->I2CM.CTRLA.bit.SWRST = 1;
     378
     379  //Wait both bits Software Reset from CTRLA and SYNCBUSY are equal to 0
     380  while(sercom->I2CM.CTRLA.bit.SWRST || sercom->I2CM.SYNCBUSY.bit.SWRST);
    328381}
    329382
     
    371424  sercom->I2CS.CTRLA.bit.MODE = I2C_SLAVE_OPERATION ;
    372425
    373   // Enable Quick Command
    374   sercom->I2CM.CTRLB.bit.QCEN = 1 ;
    375 
    376426  sercom->I2CS.ADDR.reg = SERCOM_I2CS_ADDR_ADDR( ucAddress & 0x7Ful ) | // 0x7F, select only 7 bits
    377                           SERCOM_I2CS_ADDR_ADDRMASK( 0x3FFul ) ;        // 0x3FF all bits set
     427                          SERCOM_I2CS_ADDR_ADDRMASK( 0x3FFul ) ;    // 0x3FF all bits set
    378428
    379429  // Set the interrupt register
    380   sercom->I2CS.INTENSET.reg = SERCOM_I2CS_INTENSET_AMATCH |             // Address Match
    381                               SERCOM_I2CS_INTENSET_DRDY ;               // Data Ready
     430  sercom->I2CS.INTENSET.reg = SERCOM_I2CS_INTENSET_PREC |   // Stop
     431                              SERCOM_I2CS_INTENSET_AMATCH | // Address Match
     432                              SERCOM_I2CS_INTENSET_DRDY ;   // Data Ready
    382433
    383434  while ( sercom->I2CM.SYNCBUSY.bit.SYSOP != 0 )
     
    395446
    396447  // Set master mode and enable SCL Clock Stretch mode (stretch after ACK bit)
    397   sercom->I2CM.CTRLA.reg =  SERCOM_I2CM_CTRLA_MODE( I2C_MASTER_OPERATION );
     448  sercom->I2CM.CTRLA.reg =  SERCOM_I2CM_CTRLA_MODE( I2C_MASTER_OPERATION )/* |
     449                            SERCOM_I2CM_CTRLA_SCLSM*/ ;
    398450
    399451  // Enable Smart mode and Quick Command
     452  //sercom->I2CM.CTRLB.reg =  SERCOM_I2CM_CTRLB_SMEN /*| SERCOM_I2CM_CTRLB_QCEN*/ ;
     453
    400454
    401455  // Enable all interrupts
     456//  sercom->I2CM.INTENSET.reg = SERCOM_I2CM_INTENSET_MB | SERCOM_I2CM_INTENSET_SB | SERCOM_I2CM_INTENSET_ERROR ;
    402457
    403458  // Synchronous arithmetic baudrate
     
    407462void SERCOM::prepareNackBitWIRE( void )
    408463{
    409   // Send a NACK
    410   sercom->I2CM.CTRLB.bit.ACKACT = 1;
     464  if(isMasterWIRE()) {
     465    // Send a NACK
     466    sercom->I2CM.CTRLB.bit.ACKACT = 1;
     467  } else {
     468    sercom->I2CS.CTRLB.bit.ACKACT = 1;
     469  }
    411470}
    412471
    413472void SERCOM::prepareAckBitWIRE( void )
    414473{
    415   // Send an ACK
    416   sercom->I2CM.CTRLB.bit.ACKACT = 0;
    417 }
    418 
    419 void SERCOM::prepareCommandBitsWire(SercomMasterCommandWire cmd)
    420 {
    421   sercom->I2CM.CTRLB.bit.CMD = cmd;
    422 
    423   while(sercom->I2CM.SYNCBUSY.bit.SYSOP)
    424   {
    425     // Waiting for synchronization
     474  if(isMasterWIRE()) {
     475    // Send an ACK
     476    sercom->I2CM.CTRLB.bit.ACKACT = 0;
     477  } else {
     478    sercom->I2CS.CTRLB.bit.ACKACT = 0;
     479  }
     480}
     481
     482void SERCOM::prepareCommandBitsWire(uint8_t cmd)
     483{
     484  if(isMasterWIRE()) {
     485    sercom->I2CM.CTRLB.bit.CMD = cmd;
     486
     487    while(sercom->I2CM.SYNCBUSY.bit.SYSOP)
     488    {
     489      // Waiting for synchronization
     490    }
     491  } else {
     492    sercom->I2CS.CTRLB.bit.CMD = cmd;
    426493  }
    427494}
     
    432499  address = (address << 0x1ul) | flag;
    433500
    434   // Wait idle bus mode
    435   while ( !isBusIdleWIRE() );
     501
     502  // Wait idle or owner bus mode
     503  while ( !isBusIdleWIRE() && !isBusOwnerWIRE() );
    436504
    437505  // Send start and address
    438506  sercom->I2CM.ADDR.bit.ADDR = address;
     507 
    439508
    440509  // Address Transmitted
     
    450519    while( !sercom->I2CM.INTFLAG.bit.SB )
    451520    {
     521        // If the slave NACKS the address, the MB bit will be set.
     522        // In that case, send a stop condition and return false.
     523        if (sercom->I2CM.INTFLAG.bit.MB) {
     524            sercom->I2CM.CTRLB.bit.CMD = 3; // Stop condition
     525            return false;
     526        }
    452527      // Wait transmission complete
    453528    }
     
    471546bool SERCOM::sendDataMasterWIRE(uint8_t data)
    472547{
    473         //Send data
    474         sercom->I2CM.DATA.bit.DATA = data;
    475 
    476         //Wait transmission successful
    477         while(!sercom->I2CM.INTFLAG.bit.MB);
    478 
    479         //Problems on line? nack received?
    480         if(sercom->I2CM.STATUS.bit.RXNACK)
    481                 return false;
    482         else
    483                 return true;
     548  //Send data
     549  sercom->I2CM.DATA.bit.DATA = data;
     550
     551  //Wait transmission successful
     552  while(!sercom->I2CM.INTFLAG.bit.MB) {
     553
     554    // If a bus error occurs, the MB bit may never be set.
     555    // Check the bus error bit and bail if it's set.
     556    if (sercom->I2CM.STATUS.bit.BUSERR) {
     557      return false;
     558    }
     559  }
     560
     561  //Problems on line? nack received?
     562  if(sercom->I2CM.STATUS.bit.RXNACK)
     563    return false;
     564  else
     565    return true;
    484566}
    485567
    486568bool SERCOM::sendDataSlaveWIRE(uint8_t data)
    487569{
    488         //Send data
    489         sercom->I2CS.DATA.bit.DATA = data;
    490 
    491         //Wait data transmission successful
    492         while(!sercom->I2CS.INTFLAG.bit.DRDY);
    493 
    494         //Problems on line? nack received?
    495         if(sercom->I2CS.STATUS.bit.RXNACK)
    496                 return false;
    497         else
    498                 return true;
     570  //Send data
     571  sercom->I2CS.DATA.bit.DATA = data;
     572
     573  //Wait data transmission successful
     574  while(!sercom->I2CS.INTFLAG.bit.DRDY);
     575
     576  //Problems on line? nack received?
     577  if(sercom->I2CS.STATUS.bit.RXNACK)
     578    return false;
     579  else
     580    return true;
    499581}
    500582
    501583bool SERCOM::isMasterWIRE( void )
    502584{
    503         return sercom->I2CS.CTRLA.bit.MODE == I2C_MASTER_OPERATION;
     585  return sercom->I2CS.CTRLA.bit.MODE == I2C_MASTER_OPERATION;
    504586}
    505587
    506588bool SERCOM::isSlaveWIRE( void )
    507589{
    508         return sercom->I2CS.CTRLA.bit.MODE == I2C_SLAVE_OPERATION;
     590  return sercom->I2CS.CTRLA.bit.MODE == I2C_SLAVE_OPERATION;
    509591}
    510592
    511593bool SERCOM::isBusIdleWIRE( void )
    512594{
    513         return sercom->I2CM.STATUS.bit.BUSSTATE == WIRE_IDLE_STATE;
     595  return sercom->I2CM.STATUS.bit.BUSSTATE == WIRE_IDLE_STATE;
     596}
     597
     598bool SERCOM::isBusOwnerWIRE( void )
     599{
     600  return sercom->I2CM.STATUS.bit.BUSSTATE == WIRE_OWNER_STATE;
    514601}
    515602
    516603bool SERCOM::isDataReadyWIRE( void )
    517604{
    518         return sercom->I2CS.INTFLAG.bit.DRDY;
     605  return sercom->I2CS.INTFLAG.bit.DRDY;
    519606}
    520607
    521608bool SERCOM::isStopDetectedWIRE( void )
    522609{
    523         return sercom->I2CS.INTFLAG.bit.PREC;
     610  return sercom->I2CS.INTFLAG.bit.PREC;
    524611}
    525612
    526613bool SERCOM::isRestartDetectedWIRE( void )
    527614{
    528         return sercom->I2CS.STATUS.bit.SR;
     615  return sercom->I2CS.STATUS.bit.SR;
    529616}
    530617
    531618bool SERCOM::isAddressMatch( void )
    532619{
    533         return sercom->I2CS.INTFLAG.bit.AMATCH;
     620  return sercom->I2CS.INTFLAG.bit.AMATCH;
    534621}
    535622
     
    546633int SERCOM::availableWIRE( void )
    547634{
    548         if(isMasterWIRE())
    549                 return sercom->I2CM.INTFLAG.bit.SB;
    550         else
    551                 return sercom->I2CS.INTFLAG.bit.DRDY;
     635  if(isMasterWIRE())
     636    return sercom->I2CM.INTFLAG.bit.SB;
     637  else
     638    return sercom->I2CS.INTFLAG.bit.DRDY;
    552639}
    553640
     
    572659void SERCOM::initClockNVIC( void )
    573660{
    574         uint8_t clockId = 0;
    575         IRQn_Type IdNvic;
    576 
    577         if(sercom == SERCOM0)
    578         {
    579                 clockId = GCM_SERCOM0_CORE;
    580                 IdNvic = SERCOM0_IRQn;
    581         }
    582         else if(sercom == SERCOM1)
    583         {
    584                 clockId = GCM_SERCOM1_CORE;
    585                 IdNvic = SERCOM1_IRQn;
    586         }
    587         else if(sercom == SERCOM2)
    588         {
    589                 clockId = GCM_SERCOM2_CORE;
    590                 IdNvic = SERCOM2_IRQn;
    591         }
    592         else if(sercom == SERCOM3)
    593         {
    594                 clockId = GCM_SERCOM3_CORE;
    595                 IdNvic = SERCOM3_IRQn;
    596         }
    597         else if(sercom == SERCOM4)
    598         {
    599                 clockId = GCM_SERCOM4_CORE;
    600                 IdNvic = SERCOM4_IRQn;
    601         }
    602         else if(sercom == SERCOM5)
    603         {
    604                 clockId = GCM_SERCOM5_CORE;
    605                 IdNvic = SERCOM5_IRQn;
    606         }
    607 
    608         // Setting NVIC
    609         NVIC_EnableIRQ(IdNvic);
    610         NVIC_SetPriority (IdNvic, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority */
    611 
    612         //Setting clock
    613         GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( clockId ) |       // Generic Clock 0 (SERCOMx)
    614                                                           GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
    615                                                           GCLK_CLKCTRL_CLKEN ;
    616 
    617         while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
    618         {
    619                 /* Wait for synchronization */
    620         }
    621 
    622 }
     661  uint8_t clockId = 0;
     662  IRQn_Type IdNvic=PendSV_IRQn ; // Dummy init to intercept potential error later
     663
     664  if(sercom == SERCOM0)
     665  {
     666    clockId = GCM_SERCOM0_CORE;
     667    IdNvic = SERCOM0_IRQn;
     668  }
     669  else if(sercom == SERCOM1)
     670  {
     671    clockId = GCM_SERCOM1_CORE;
     672    IdNvic = SERCOM1_IRQn;
     673  }
     674  else if(sercom == SERCOM2)
     675  {
     676    clockId = GCM_SERCOM2_CORE;
     677    IdNvic = SERCOM2_IRQn;
     678  }
     679  else if(sercom == SERCOM3)
     680  {
     681    clockId = GCM_SERCOM3_CORE;
     682    IdNvic = SERCOM3_IRQn;
     683  }
     684  else if(sercom == SERCOM4)
     685  {
     686    clockId = GCM_SERCOM4_CORE;
     687    IdNvic = SERCOM4_IRQn;
     688  }
     689  else if(sercom == SERCOM5)
     690  {
     691    clockId = GCM_SERCOM5_CORE;
     692    IdNvic = SERCOM5_IRQn;
     693  }
     694
     695  if ( IdNvic == PendSV_IRQn )
     696  {
     697    // We got a problem here
     698    return ;
     699  }
     700
     701  // Setting NVIC
     702  NVIC_EnableIRQ(IdNvic);
     703  NVIC_SetPriority (IdNvic, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority */
     704
     705  //Setting clock
     706  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( clockId ) | // Generic Clock 0 (SERCOMx)
     707                      GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
     708                      GCLK_CLKCTRL_CLKEN ;
     709
     710  while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
     711  {
     712    /* Wait for synchronization */
     713  }
     714}
Note: See TracChangeset for help on using the changeset viewer.