diff --git a/cores/arduino/ard_sup/ap3_iomaster.h b/cores/arduino/ard_sup/ap3_iomaster.h index 867dda1..fab9e58 100644 --- a/cores/arduino/ard_sup/ap3_iomaster.h +++ b/cores/arduino/ard_sup/ap3_iomaster.h @@ -28,24 +28,21 @@ SOFTWARE. #include "Arduino.h" #include "ap3_iomaster_types.h" -class IOMaster { +class IOMaster +{ private: protected: - uint8_t _instance; - void* _handle; + uint8_t _instance; + void *_handle; am_hal_iom_config_t _config; public: IOMaster(uint8_t instance); - ap3_err_t initialize( void ); - ap3_err_t initialize(am_hal_iom_config_t config); - ap3_err_t deinitialize( void ); + ap3_err_t initialize(BitOrder bitOrder); + ap3_err_t initialize(am_hal_iom_config_t config, BitOrder bitOrder); + ap3_err_t deinitialize(void); }; - - -ap3_err_t ap3_iom_pad_funcsel( uint8_t instance, ap3_iom_pad_type_e type, ap3_gpio_pad_t* pad, uint8_t* funcsel ); - - +ap3_err_t ap3_iom_pad_funcsel(uint8_t instance, ap3_iom_pad_type_e type, ap3_gpio_pad_t *pad, uint8_t *funcsel); #endif // _AP3_IOMASTER_H_ \ No newline at end of file diff --git a/cores/arduino/ard_sup/iomaster/ap3_iomaster.cpp b/cores/arduino/ard_sup/iomaster/ap3_iomaster.cpp index 098cb25..db573bc 100644 --- a/cores/arduino/ard_sup/iomaster/ap3_iomaster.cpp +++ b/cores/arduino/ard_sup/iomaster/ap3_iomaster.cpp @@ -20,137 +20,266 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - #include "ap3_iomaster.h" -IOMaster::IOMaster(uint8_t instance){ +IOMaster::IOMaster(uint8_t instance) +{ _instance = instance; } -ap3_err_t IOMaster::initialize( void ){ - return initialize(_config); +ap3_err_t IOMaster::initialize(BitOrder bitOrder) +{ + return initialize(_config, bitOrder); } -ap3_err_t IOMaster::initialize(am_hal_iom_config_t config){ +ap3_err_t IOMaster::initialize(am_hal_iom_config_t config, BitOrder bitOrder) +{ uint32_t retVal32 = 0; _config = config; am_hal_iom_disable(_handle); am_hal_iom_uninitialize(_handle); - + retVal32 = am_hal_iom_initialize(_instance, &_handle); - if (retVal32 != AM_HAL_STATUS_SUCCESS){ return AP3_ERR; } + if (retVal32 != AM_HAL_STATUS_SUCCESS) + { + return AP3_ERR; + } retVal32 = am_hal_iom_power_ctrl(_handle, AM_HAL_SYSCTRL_WAKE, false); - if (retVal32 != AM_HAL_STATUS_SUCCESS){ return AP3_ERR; } - + if (retVal32 != AM_HAL_STATUS_SUCCESS) + { + return AP3_ERR; + } + retVal32 = am_hal_iom_configure(_handle, &_config); - if (retVal32 != AM_HAL_STATUS_SUCCESS){ return AP3_ERR; } + if (retVal32 != AM_HAL_STATUS_SUCCESS) + { + return AP3_ERR; + } retVal32 = am_hal_iom_enable(_handle); - if (retVal32 != AM_HAL_STATUS_SUCCESS){ return AP3_ERR; } + if (retVal32 != AM_HAL_STATUS_SUCCESS) + { + return AP3_ERR; + } + + //Arduino defines LSBFIRST as 0, Ambiq HAL defines this bit as 1 + //So we invert + uint8_t temp = (bitOrder ? 0 : 1); + retVal32 = am_hal_iom_control(_handle, AM_HAL_IOM_REQ_SPI_LSB, &temp); + if (retVal32 != AM_HAL_STATUS_SUCCESS) + { + return AP3_ERR; + } + + return AP3_OK; // Configure the IOM pins. (Must be done by the inherited classes [this is just a reminder]) } -ap3_err_t IOMaster::deinitialize( void ){ +ap3_err_t IOMaster::deinitialize(void) +{ uint32_t retVal32 = 0; - + retVal32 = am_hal_iom_disable(_handle); - if( retVal32 != AM_HAL_STATUS_SUCCESS){ return AP3_ERR; } + if (retVal32 != AM_HAL_STATUS_SUCCESS) + { + return AP3_ERR; + } retVal32 = am_hal_iom_uninitialize(_handle); - if( retVal32 != AM_HAL_STATUS_SUCCESS){ return AP3_ERR; } + if (retVal32 != AM_HAL_STATUS_SUCCESS) + { + return AP3_ERR; + } return AP3_OK; } - -ap3_err_t ap3_iom_pad_funcsel( uint8_t instance, ap3_iom_pad_type_e type, ap3_gpio_pad_t* pad, uint8_t* funcsel){ +ap3_err_t ap3_iom_pad_funcsel(uint8_t instance, ap3_iom_pad_type_e type, ap3_gpio_pad_t *pad, uint8_t *funcsel) +{ ap3_err_t retval = AP3_OK; - switch( instance ){ - case 0 : - switch( type ){ - case AP3_IOM_I2C_SCL : *pad = 5; *funcsel = AM_HAL_PIN_5_M0SCL; break; - case AP3_IOM_I2C_SDA : *pad = 6; *funcsel = AM_HAL_PIN_6_M0SDAWIR3; break; - case AP3_IOM_SPI_SCLK : *pad = 5; *funcsel = AM_HAL_PIN_5_M0SCK; break; - case AP3_IOM_SPI_MOSI : *pad = 7; *funcsel = AM_HAL_PIN_7_M0MOSI; break; - case AP3_IOM_SPI_MISO : *pad = 6; *funcsel = AM_HAL_PIN_6_M0MISO; break; - default : - goto invalid_args; - break; - } - break; - - case 1 : - switch( type ){ - case AP3_IOM_I2C_SCL : *pad = 8; *funcsel = AM_HAL_PIN_8_M1SCL; break; - case AP3_IOM_I2C_SDA : *pad = 9; *funcsel = AM_HAL_PIN_9_M1SDAWIR3; break; - case AP3_IOM_SPI_SCLK : *pad = 8; *funcsel = AM_HAL_PIN_8_M1SCK; break; - case AP3_IOM_SPI_MOSI : *pad = 10; *funcsel = AM_HAL_PIN_10_M1MOSI; break; - case AP3_IOM_SPI_MISO : *pad = 9; *funcsel = AM_HAL_PIN_9_M1MISO; break; - default : - goto invalid_args; - break; - } - break; - - case 2 : - switch( type ){ - case AP3_IOM_I2C_SCL : *pad = 27; *funcsel = AM_HAL_PIN_27_M2SCL; break; - case AP3_IOM_I2C_SDA : *pad = 25; *funcsel = AM_HAL_PIN_25_M2SDAWIR3; break; - case AP3_IOM_SPI_SCLK : *pad = 27; *funcsel = AM_HAL_PIN_27_M2SCK; break; - case AP3_IOM_SPI_MOSI : *pad = 28; *funcsel = AM_HAL_PIN_28_M2MOSI; break; - case AP3_IOM_SPI_MISO : *pad = 25; *funcsel = AM_HAL_PIN_25_M2MISO; break; - default : - goto invalid_args; - break; - } - break; - - case 3 : - switch( type ){ - case AP3_IOM_I2C_SCL : *pad = 42; *funcsel = AM_HAL_PIN_42_M3SCL; break; - case AP3_IOM_I2C_SDA : *pad = 43; *funcsel = AM_HAL_PIN_43_M3SDAWIR3; break; - case AP3_IOM_SPI_SCLK : *pad = 42; *funcsel = AM_HAL_PIN_42_M3SCK; break; - case AP3_IOM_SPI_MOSI : *pad = 38; *funcsel = AM_HAL_PIN_38_M3MOSI; break; - case AP3_IOM_SPI_MISO : *pad = 43; *funcsel = AM_HAL_PIN_43_M3MISO; break; - default : - goto invalid_args; - break; - } - break; - - case 4 : - switch( type ){ - case AP3_IOM_I2C_SCL : *pad = 39; *funcsel = AM_HAL_PIN_39_M4SCL; break; - case AP3_IOM_I2C_SDA : *pad = 40; *funcsel = AM_HAL_PIN_40_M4SDAWIR3; break; - case AP3_IOM_SPI_SCLK : *pad = 39; *funcsel = AM_HAL_PIN_39_M4SCK; break; - case AP3_IOM_SPI_MOSI : *pad = 44; *funcsel = AM_HAL_PIN_44_M4MOSI; break; - case AP3_IOM_SPI_MISO : *pad = 40; *funcsel = AM_HAL_PIN_40_M4MISO; break; - default : - goto invalid_args; - break; - } - break; - - case 5 : - switch( type ){ - case AP3_IOM_I2C_SCL : *pad = 48; *funcsel = AM_HAL_PIN_48_M5SCL; break; - case AP3_IOM_I2C_SDA : *pad = 49; *funcsel = AM_HAL_PIN_49_M5SDAWIR3; break; - case AP3_IOM_SPI_SCLK : *pad = 48; *funcsel = AM_HAL_PIN_48_M5SCK; break; - case AP3_IOM_SPI_MOSI : *pad = 47; *funcsel = AM_HAL_PIN_47_M5MOSI; break; - case AP3_IOM_SPI_MISO : *pad = 49; *funcsel = AM_HAL_PIN_49_M5MISO; break; - default : - goto invalid_args; - break; - } - break; - - default : + switch (instance) + { + case 0: + switch (type) + { + case AP3_IOM_I2C_SCL: + *pad = 5; + *funcsel = AM_HAL_PIN_5_M0SCL; + break; + case AP3_IOM_I2C_SDA: + *pad = 6; + *funcsel = AM_HAL_PIN_6_M0SDAWIR3; + break; + case AP3_IOM_SPI_SCLK: + *pad = 5; + *funcsel = AM_HAL_PIN_5_M0SCK; + break; + case AP3_IOM_SPI_MOSI: + *pad = 7; + *funcsel = AM_HAL_PIN_7_M0MOSI; + break; + case AP3_IOM_SPI_MISO: + *pad = 6; + *funcsel = AM_HAL_PIN_6_M0MISO; + break; + default: goto invalid_args; break; + } + break; + + case 1: + switch (type) + { + case AP3_IOM_I2C_SCL: + *pad = 8; + *funcsel = AM_HAL_PIN_8_M1SCL; + break; + case AP3_IOM_I2C_SDA: + *pad = 9; + *funcsel = AM_HAL_PIN_9_M1SDAWIR3; + break; + case AP3_IOM_SPI_SCLK: + *pad = 8; + *funcsel = AM_HAL_PIN_8_M1SCK; + break; + case AP3_IOM_SPI_MOSI: + *pad = 10; + *funcsel = AM_HAL_PIN_10_M1MOSI; + break; + case AP3_IOM_SPI_MISO: + *pad = 9; + *funcsel = AM_HAL_PIN_9_M1MISO; + break; + default: + goto invalid_args; + break; + } + break; + + case 2: + switch (type) + { + case AP3_IOM_I2C_SCL: + *pad = 27; + *funcsel = AM_HAL_PIN_27_M2SCL; + break; + case AP3_IOM_I2C_SDA: + *pad = 25; + *funcsel = AM_HAL_PIN_25_M2SDAWIR3; + break; + case AP3_IOM_SPI_SCLK: + *pad = 27; + *funcsel = AM_HAL_PIN_27_M2SCK; + break; + case AP3_IOM_SPI_MOSI: + *pad = 28; + *funcsel = AM_HAL_PIN_28_M2MOSI; + break; + case AP3_IOM_SPI_MISO: + *pad = 25; + *funcsel = AM_HAL_PIN_25_M2MISO; + break; + default: + goto invalid_args; + break; + } + break; + + case 3: + switch (type) + { + case AP3_IOM_I2C_SCL: + *pad = 42; + *funcsel = AM_HAL_PIN_42_M3SCL; + break; + case AP3_IOM_I2C_SDA: + *pad = 43; + *funcsel = AM_HAL_PIN_43_M3SDAWIR3; + break; + case AP3_IOM_SPI_SCLK: + *pad = 42; + *funcsel = AM_HAL_PIN_42_M3SCK; + break; + case AP3_IOM_SPI_MOSI: + *pad = 38; + *funcsel = AM_HAL_PIN_38_M3MOSI; + break; + case AP3_IOM_SPI_MISO: + *pad = 43; + *funcsel = AM_HAL_PIN_43_M3MISO; + break; + default: + goto invalid_args; + break; + } + break; + + case 4: + switch (type) + { + case AP3_IOM_I2C_SCL: + *pad = 39; + *funcsel = AM_HAL_PIN_39_M4SCL; + break; + case AP3_IOM_I2C_SDA: + *pad = 40; + *funcsel = AM_HAL_PIN_40_M4SDAWIR3; + break; + case AP3_IOM_SPI_SCLK: + *pad = 39; + *funcsel = AM_HAL_PIN_39_M4SCK; + break; + case AP3_IOM_SPI_MOSI: + *pad = 44; + *funcsel = AM_HAL_PIN_44_M4MOSI; + break; + case AP3_IOM_SPI_MISO: + *pad = 40; + *funcsel = AM_HAL_PIN_40_M4MISO; + break; + default: + goto invalid_args; + break; + } + break; + + case 5: + switch (type) + { + case AP3_IOM_I2C_SCL: + *pad = 48; + *funcsel = AM_HAL_PIN_48_M5SCL; + break; + case AP3_IOM_I2C_SDA: + *pad = 49; + *funcsel = AM_HAL_PIN_49_M5SDAWIR3; + break; + case AP3_IOM_SPI_SCLK: + *pad = 48; + *funcsel = AM_HAL_PIN_48_M5SCK; + break; + case AP3_IOM_SPI_MOSI: + *pad = 47; + *funcsel = AM_HAL_PIN_47_M5MOSI; + break; + case AP3_IOM_SPI_MISO: + *pad = 49; + *funcsel = AM_HAL_PIN_49_M5MISO; + break; + default: + goto invalid_args; + break; + } + break; + + default: + goto invalid_args; + break; } return retval; diff --git a/libraries/SPI/src/SPI.cpp b/libraries/SPI/src/SPI.cpp index 4f441a1..0cfd1a9 100644 --- a/libraries/SPI/src/SPI.cpp +++ b/libraries/SPI/src/SPI.cpp @@ -113,9 +113,9 @@ void SPIClass::config(SPISettings settings) _config.eInterfaceMode = AM_HAL_IOM_SPI_MODE; _config.ui32ClockFreq = settings.clockFreq; _config.eSpiMode = settings.dataMode; - _order = settings.bitOrder; + _bitOrder = settings.bitOrder; - initialize(); // Initialize the IOM + initialize(_bitOrder); // Initialize the IOM } void SPIClass::end() @@ -203,25 +203,24 @@ void SPIClass::endTransaction(void) // } } +//This sets local/private var _bitOrder +//_bitOrder is passed any time initialize is called due to HAL hack to get SPILSB bit set void SPIClass::setBitOrder(BitOrder order) { - _order = order; + _bitOrder = order; } void SPIClass::setDataMode(uint8_t mode) { _config.eSpiMode = (am_hal_iom_spi_mode_e)mode; - initialize(); + initialize(_bitOrder); } -// void SPIClass::setClockDivider(uint8_t div) -// { -// // if (div < SPI_MIN_CLOCK_DIVIDER) { -// // _p_sercom->setBaudrateSPI(SPI_MIN_CLOCK_DIVIDER); -// // } else { -// // _p_sercom->setBaudrateSPI(div); -// // } -// } +void SPIClass::setClockDivider(uint8_t div) +{ + _config.ui32ClockFreq = F_CPU / div; + initialize(_bitOrder); +} byte SPIClass::transfer(uint8_t data) { @@ -241,7 +240,7 @@ uint16_t SPIClass::transfer16(uint16_t data) t.val = data; - if (_order == LSBFIRST) + if (_bitOrder == LSBFIRST) { t.lsb = transfer(t.lsb); t.msb = transfer(t.msb); diff --git a/libraries/SPI/src/SPI.h b/libraries/SPI/src/SPI.h index 8fef3ed..0c63a23 100644 --- a/libraries/SPI/src/SPI.h +++ b/libraries/SPI/src/SPI.h @@ -38,34 +38,43 @@ #define SPI_MODE2 AM_HAL_IOM_SPI_MODE_2 #define SPI_MODE3 AM_HAL_IOM_SPI_MODE_3 -typedef enum{ +typedef enum +{ ap3_spi_tx_only = 1, ap3_spi_rx_only = 2, ap3_spi_full_duplex = 3, -}ap3_spi_duplex_e; - -class SPISettings { - public: - SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) { - if (__builtin_constant_p(clock)) { +} ap3_spi_duplex_e; + +class SPISettings +{ +public: + SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) + { + if (__builtin_constant_p(clock)) + { init_AlwaysInline(clock, bitOrder, dataMode); - } else { + } + else + { init_MightInline(clock, bitOrder, dataMode); } } // Default speed set to 4MHz, SPI mode set to MODE 0 and Bit order set to MSB first. - SPISettings() { - init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0); + SPISettings() + { + init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0); } - private: - public: // temporary - void init_MightInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) { +private: +public: // temporary + void init_MightInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) + { init_AlwaysInline(clock, bitOrder, dataMode); } - void init_AlwaysInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) __attribute__((__always_inline__)) { + void init_AlwaysInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) __attribute__((__always_inline__)) + { this->clockFreq = clock; this->bitOrder = bitOrder; this->dataMode = (am_hal_iom_spi_mode_e)dataMode; @@ -78,8 +87,9 @@ class SPISettings { friend class SPIClass; }; -class SPIClass : public IOMaster { - public: +class SPIClass : public IOMaster +{ +public: SPIClass(uint8_t iom_instance); SPIClass(uint8_t iom_instance, ap3_spi_duplex_e duplex); @@ -104,22 +114,22 @@ class SPIClass : public IOMaster { void setBitOrder(BitOrder order); void setDataMode(uint8_t uc_mode); - // void setClockDivider(uint8_t uc_div); + void setClockDivider(uint8_t div); + + void _transfer(void *buf_out = NULL, void *buf_in = NULL, size_t count = 0); private: void config(SPISettings settings); - void _transfer(void* buf_out = NULL, void* buf_in = NULL, size_t count = 0); - // Bit Order (need a better way to handle this) - BitOrder _order; + BitOrder _bitOrder = MSBFIRST; // Duplex ap3_spi_duplex_e _duplex; // Pads (for reference) - ap3_gpio_pin_t _padSCLK; - ap3_gpio_pin_t _padMOSI; - ap3_gpio_pin_t _padMISO; + ap3_gpio_pin_t _padSCLK; + ap3_gpio_pin_t _padMOSI; + ap3_gpio_pin_t _padMISO; // SERCOM *_p_sercom; // uint8_t _uc_pinMiso; @@ -136,34 +146,34 @@ class SPIClass : public IOMaster { }; #if SPI_INTERFACES_COUNT > 0 - extern SPIClass SPI; +extern SPIClass SPI; #endif #if SPI_INTERFACES_COUNT > 1 - extern SPIClass SPI1; +extern SPIClass SPI1; #endif #if SPI_INTERFACES_COUNT > 2 - extern SPIClass SPI2; +extern SPIClass SPI2; #endif #if SPI_INTERFACES_COUNT > 3 - extern SPIClass SPI3; +extern SPIClass SPI3; #endif #if SPI_INTERFACES_COUNT > 4 - extern SPIClass SPI4; +extern SPIClass SPI4; #endif #if SPI_INTERFACES_COUNT > 5 - extern SPIClass SPI5; +extern SPIClass SPI5; #endif // For compatibility with sketches designed for AVR @ 16 MHz // New programs should use SPI.beginTransaction to set the SPI clock #if F_CPU == 48000000 - #define SPI_CLOCK_DIV2 6 - #define SPI_CLOCK_DIV4 12 - #define SPI_CLOCK_DIV8 24 - #define SPI_CLOCK_DIV16 48 - #define SPI_CLOCK_DIV32 96 - #define SPI_CLOCK_DIV64 192 - #define SPI_CLOCK_DIV128 255 +#define SPI_CLOCK_DIV2 6 +#define SPI_CLOCK_DIV4 12 +#define SPI_CLOCK_DIV8 24 +#define SPI_CLOCK_DIV16 48 +#define SPI_CLOCK_DIV32 96 +#define SPI_CLOCK_DIV64 192 +#define SPI_CLOCK_DIV128 255 #endif #endif