diff --git a/include/sta/arduino/not_implemented.hpp b/include/sta/arduino/not_implemented.hpp deleted file mode 100644 index 5c8d8b3..0000000 --- a/include/sta/arduino/not_implemented.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef STA_CORE_ARDUINO_NOT_IMPLEMENTED_HPP -#define STA_CORE_ARDUINO_NOT_IMPLEMENTED_HPP - - -/** - * @defgroup sta_core_arduino Arduino - * @ingroup sta_core_platforms - * @brief Modules implemented for the Arduino platform. - */ - - -#endif // STA_CORE_ARDUINO_NOT_IMPLEMENTED_HPP \ No newline at end of file diff --git a/include/sta/can/controller.hpp b/include/sta/bus/can/controller.hpp similarity index 96% rename from include/sta/can/controller.hpp rename to include/sta/bus/can/controller.hpp index fbadb59..0c6f212 100644 --- a/include/sta/can/controller.hpp +++ b/include/sta/bus/can/controller.hpp @@ -12,9 +12,9 @@ */ -#include -#include -#include +#include +#include +#include namespace sta diff --git a/include/sta/can/filter.hpp b/include/sta/bus/can/filter.hpp similarity index 96% rename from include/sta/can/filter.hpp rename to include/sta/bus/can/filter.hpp index 0071139..1499eea 100644 --- a/include/sta/can/filter.hpp +++ b/include/sta/bus/can/filter.hpp @@ -5,7 +5,7 @@ #ifndef STA_CORE_CAN_FILTER_HPP #define STA_CORE_CAN_FILTER_HPP -#include +#include #include diff --git a/include/sta/can/headers.hpp b/include/sta/bus/can/headers.hpp similarity index 96% rename from include/sta/can/headers.hpp rename to include/sta/bus/can/headers.hpp index 24536c5..0214434 100644 --- a/include/sta/can/headers.hpp +++ b/include/sta/bus/can/headers.hpp @@ -5,7 +5,7 @@ #ifndef STA_CORE_CAN_HEADERS_HPP #define STA_CORE_CAN_HEADERS_HPP -#include +#include #include diff --git a/include/sta/can/id.hpp b/include/sta/bus/can/id.hpp similarity index 100% rename from include/sta/can/id.hpp rename to include/sta/bus/can/id.hpp diff --git a/include/sta/can/iter.hpp b/include/sta/bus/can/iter.hpp similarity index 100% rename from include/sta/can/iter.hpp rename to include/sta/bus/can/iter.hpp diff --git a/include/sta/can/subscribable.hpp b/include/sta/bus/can/subscribable.hpp similarity index 93% rename from include/sta/can/subscribable.hpp rename to include/sta/bus/can/subscribable.hpp index 1d84080..2f5d600 100644 --- a/include/sta/can/subscribable.hpp +++ b/include/sta/bus/can/subscribable.hpp @@ -5,8 +5,8 @@ #ifndef STA_CORE_CAN_SUBSCRIBABLE_HPP #define STA_CORE_CAN_SUBSCRIBABLE_HPP -#include -#include +#include +#include namespace sta @@ -96,7 +96,7 @@ namespace sta } // namespace sta -#include +#include -#endif // STA_CORE_CAN_SUBSCRIBABLE_HPP +#endif // STA_CORE_CAN_SUBSCRIBABLE_HPP \ No newline at end of file diff --git a/include/sta/can/subscribable.tpp b/include/sta/bus/can/subscribable.tpp similarity index 100% rename from include/sta/can/subscribable.tpp rename to include/sta/bus/can/subscribable.tpp diff --git a/include/sta/spi/device.hpp b/include/sta/bus/device.hpp similarity index 58% rename from include/sta/spi/device.hpp rename to include/sta/bus/device.hpp index 7821bff..c6dc208 100644 --- a/include/sta/spi/device.hpp +++ b/include/sta/bus/device.hpp @@ -1,33 +1,21 @@ -/** - * @file - * @brief SPI bus peripheral device. - */ -#ifndef STA_CORE_SPI_DEVICE_HPP -#define STA_CORE_SPI_DEVICE_HPP - -#include -#include - -#include -#include +#ifndef STA_CORE_BUS_SERIAL_DEVICE_HPP +#define STA_CORE_BUS_SERIAL_DEVICE_HPP +#include namespace sta { /** - * @brief Peripheral device connected via SPI. - * - * @ingroup sta_core_spi - */ - class SPIDevice + * @brief Abstract device for serial communication. + */ + class Device { public: - /** + /** * @param intf %SPI hardware interface * @param csPin Chip select pin */ - SPIDevice(SPI * intf, GpioPin * csPin); - + Device(Interface * intf); /** * @brief Start transmission with device. @@ -35,6 +23,7 @@ namespace sta * Must be called before any I/O operations. */ void beginTransmission(); + /** * @brief End transmission with device. * @@ -42,19 +31,20 @@ namespace sta */ void endTransmission(); - /** * @brief Send single byte of data. * * @param value 8-bit value */ void transfer(uint8_t value); + /** * @brief Send two bytes of data. * * @param value 16-bit value */ void transfer16(uint16_t value); + /** * @brief Send data from buffer. * @@ -62,14 +52,7 @@ namespace sta * @param size Number of bytes to transfer */ void transfer(const uint8_t * buffer, size_t size); - /** - * @brief Send and receive data simultaneously. - * - * @param txBuffer Send buffer - * @param rxBuffer Receive buffer - * @param size Number of bytes to transfer - */ - void transfer(const uint8_t * txBuffer, uint8_t * rxBuffer, size_t size); + /** * @brief Read incoming data to buffer. * @@ -78,7 +61,6 @@ namespace sta */ void receive(uint8_t * buffer, size_t size); - /** * @brief Send byte value repeatedly. * @@ -87,29 +69,21 @@ namespace sta */ void fill(uint8_t value, size_t count); + protected: + /** + * @brief Activate device.. + */ + virtual void select() = 0; /** - * @brief Get %SPI interface settings. - * - * @return SPI settings + * @brief Deactivate device.. */ - const SpiSettings & settings() const; - - - /** - * @brief Activate device via CS pin. - */ - void select(); - /** - * @brief Deactivate device via CS pin. - */ - void deselect(); + virtual void deselect() = 0; private: - SPI * intf_; /**< %SPI hardware interface */ - GpioPin * csPin_; /**< Chip select pin */ + Interface * intf_; + bool selected_ = false; }; } // namespace sta - -#endif // STA_CORE_SPI_DEVICE_HPP +#endif // STA_CORE_BUS_SERIAL_DEVICE_HPP diff --git a/include/sta/bus/i2c/device.hpp b/include/sta/bus/i2c/device.hpp new file mode 100644 index 0000000..ec6fb7b --- /dev/null +++ b/include/sta/bus/i2c/device.hpp @@ -0,0 +1,39 @@ +#ifndef STA_CORE_I2C_DEVICE_HPP +#define STA_CORE_I2C_DEVICE_HPP + +#include +#include + +namespace sta +{ + /** + * @brief Peripheral device connected via I2c. + * + * @ingroup sta_core_i2c + */ + class I2CDevice : public Device + { + public: + /** + * @param intf %I2C hardware interface + * @param csPin The peripheral's address. + */ + I2CDevice(I2C * intf, int address, bool master=true, bool blocking=true); + + protected: + void select() override; + void deselect() override; + + private: + I2C * intf_; + int address_; /**< device address */ + int master_; /**< is the mcu the master? */ + int blocking_; /**< blocking or non-blocking transmits / receives */ + }; + +} // namespace sta + + + + +#endif // STA_CORE_I2C_DEVICE_HPP diff --git a/include/sta/bus/i2c/i2c.hpp b/include/sta/bus/i2c/i2c.hpp new file mode 100644 index 0000000..1af5571 --- /dev/null +++ b/include/sta/bus/i2c/i2c.hpp @@ -0,0 +1,40 @@ +#ifndef STA_CORE_I2C_I2C_HPP +#define STA_CORE_I2C_I2C_HPP + +#include +#include + +#include +#include + +namespace sta +{ + /** + * @brief Interface class for %I2C hardware. + * + * Represents a single %I2C bus that can be shared by multiple devices. + * + * @ingroup sta_core_i2c + */ + class I2C : public Interface + { + public: + I2C(Mutex * mutex=nullptr); + + /** + * @brief Specify the mode of communication via the bus. + * + * @param address The peripheral's address to communicate with. + * @param master Whether the mcu is a master or slave. + * @param blocking Whether to use blocking or non-blocking transmits / receives. + */ + void setSettings(uint16_t address, bool master, bool blocking); + + protected: + uint16_t address_; + bool master_; + bool blocking_; + }; +} // namespace sta + +#endif // STA_CORE_I2C_I2C_HPP diff --git a/include/sta/spi/spi.hpp b/include/sta/bus/interface.hpp similarity index 57% rename from include/sta/spi/spi.hpp rename to include/sta/bus/interface.hpp index 5186cbe..e4a0cd8 100644 --- a/include/sta/spi/spi.hpp +++ b/include/sta/bus/interface.hpp @@ -1,35 +1,20 @@ -/** - * @file - * @brief SPI bus software interface. - */ -#ifndef STA_CORE_SPI_SPI_HPP -#define STA_CORE_SPI_SPI_HPP +#ifndef STA_CORE_BUS_SERIAL_INTERFACE_HPP +#define STA_CORE_BUS_SERIAL_INTERFACE_HPP #include -#include -#include #include - +#include namespace sta { /** - * @brief Interface class for %SPI hardware. - * - * Represents a single %SPI bus that can be shared by multiple devices. - * - * @ingroup sta_core_spi - */ - class SPI + * @brief Abstract interface for serial communication. + */ + class Interface { public: - /** - * @param settings %SPI bus settings - * @param mutex Mutex object for managing shared access. Pass nullptr for no access control - */ - SPI(const SPISettings & settings, Mutex * mutex = nullptr); - + Interface(Mutex * mutex); /** * @brief Send single byte of data. @@ -50,14 +35,6 @@ namespace sta * @param size Number of bytes to transfer */ virtual void transfer(const uint8_t * buffer, size_t size) = 0; - /** - * @brief Send and receive data simultaneously. - * - * @param txBuffer Send buffer - * @param rxBuffer Receive buffer - * @param size Number of bytes to transfer - */ - virtual void transfer(const uint8_t * txBuffer, uint8_t * rxBuffer, size_t size) = 0; /** * @brief Read incoming data to buffer. * @@ -66,7 +43,6 @@ namespace sta */ virtual void receive(uint8_t * buffer, size_t size) = 0; - /** * @brief Send byte value repeatedly. * @@ -75,15 +51,6 @@ namespace sta */ virtual void fill(uint8_t value, size_t count) = 0; - - /** - * @brief Get %SPI interface settings. - * - * @return %SPI settings - */ - const SPISettings & settings() const; - - /** * @brief Acquire usage rights to use the interface. * @@ -97,11 +64,15 @@ namespace sta */ virtual void release(); + /** + * @returns true if the interface has been aquired. + */ + bool isAcquired(); private: - SPISettings settings_; /**< %SPI settings */ - Mutex * mutex_; /**< Mutex object */ + Mutex * mutex_; + bool acquired_ = false; }; } // namespace sta -#endif // STA_CORE_SPI_SPI_HPP +#endif // STA_CORE_BUS_SERIAL_INTERFACE_HPP diff --git a/include/sta/bus/spi/device.hpp b/include/sta/bus/spi/device.hpp new file mode 100644 index 0000000..adeed46 --- /dev/null +++ b/include/sta/bus/spi/device.hpp @@ -0,0 +1,60 @@ +/** + * @file + * @brief SPI bus peripheral device. + */ +#ifndef STA_CORE_SPI_DEVICE_HPP +#define STA_CORE_SPI_DEVICE_HPP + +#include +#include +#include + +#include +#include + + +namespace sta +{ + /** + * @brief Peripheral device connected via SPI. + * + * @ingroup sta_core_spi + */ + class SPIDevice : public Device + { + public: + /** + * @param intf %SPI hardware interface + * @param csPin Chip select pin + */ + SPIDevice(SPI * intf, GpioPin * csPin); + + /** + * @brief Send and receive data simultaneously. + * + * @param txBuffer Send buffer + * @param rxBuffer Receive buffer + * @param size Number of bytes to transfer + */ + void transfer(const uint8_t * txBuffer, uint8_t * rxBuffer, size_t size); + + /** + * @brief Get %SPI interface settings. + * + * @return SPI settings + */ + const SPISettings & settings() const; + + protected: + void select() override; + + void deselect() override; + + private: + SPI * intf_; /**< %SPI hardware interface */ + GpioPin * csPin_; /**< Chip select pin */ + }; +} // namespace sta + + +#endif // STA_CORE_SPI_DEVICE_HPP diff --git a/include/sta/spi/settings.hpp b/include/sta/bus/spi/settings.hpp similarity index 99% rename from include/sta/spi/settings.hpp rename to include/sta/bus/spi/settings.hpp index 35b7433..dea4618 100644 --- a/include/sta/spi/settings.hpp +++ b/include/sta/bus/spi/settings.hpp @@ -5,17 +5,14 @@ #ifndef STA_CORE_SPI_SETTINGS_HPP #define STA_CORE_SPI_SETTINGS_HPP - /** * @defgroup sta_core_spi SPI * @ingroup sta_core * @brief SPI interface. */ - #include - namespace sta { /** diff --git a/include/sta/bus/spi/spi.hpp b/include/sta/bus/spi/spi.hpp new file mode 100644 index 0000000..2d0dc14 --- /dev/null +++ b/include/sta/bus/spi/spi.hpp @@ -0,0 +1,56 @@ +/** + * @file + * @brief SPI bus software interface. + */ +#ifndef STA_CORE_SPI_SPI_HPP +#define STA_CORE_SPI_SPI_HPP + +#include +#include +#include + +#include +#include + + +namespace sta +{ + /** + * @brief Interface class for %SPI hardware. + * + * Represents a single %SPI bus that can be shared by multiple devices. + * + * @ingroup sta_core_spi + */ + class SPI : public Interface + { + public: + /** + * @param settings %SPI bus settings + * @param mutex Mutex object for managing shared access. Pass nullptr for no access control + */ + SPI(const SPISettings & settings, Mutex * mutex = nullptr); + + /** + * @brief Send and receive data simultaneously. + * + * @param txBuffer Send buffer + * @param rxBuffer Receive buffer + * @param size Number of bytes to transfer + */ + virtual void transfer(const uint8_t * txBuffer, uint8_t * rxBuffer, size_t size) = 0; + + /** + * @brief Get %SPI interface settings. + * + * @return %SPI settings + */ + const SPISettings & settings(); + + private: + SPISettings settings_; /**< %SPI settings */ + }; +} // namespace sta + + +#endif // STA_CORE_SPI_SPI_HPP diff --git a/include/sta/bus/uart/settings.hpp b/include/sta/bus/uart/settings.hpp new file mode 100644 index 0000000..c3bbe2b --- /dev/null +++ b/include/sta/bus/uart/settings.hpp @@ -0,0 +1,24 @@ +#ifndef STA_CORE_UART_SETTINGS_HPP +#define STA_CORE_UART_SETTINGS_HPP + +#include + +namespace sta +{ + enum class UARTMode + { + RX, + TX, + RX_TX + }; + + /** + * @brief %UART settings. + */ + struct UARTSettings + { + UARTMode mode; + }; +} // namespace sta + +#endif // STA_CORE_UART_SETTINGS_HPP diff --git a/include/sta/bus/uart/uart.hpp b/include/sta/bus/uart/uart.hpp new file mode 100644 index 0000000..0460c3e --- /dev/null +++ b/include/sta/bus/uart/uart.hpp @@ -0,0 +1,29 @@ +#ifndef STA_CORE_UART_UART_HPP +#define STA_CORE_UART_UART_HPP + +#include +#include + +namespace sta +{ + class UART : public Interface + { + public: + /** + * @param settings %UART bus settings + * @param mutex Mutex object for managing shared access. Pass nullptr for no access control + */ + UART(UARTSettings & settings, Mutex * mutex=nullptr); + + /** + * @brief Get %UART interface settings. + * + * @return %UART settings + */ + const UARTSettings & settings(); + private: + UARTSettings settings_; /**< %UART settings */ + }; +} // namespace sta + +#endif // STA_CORE_UART_UART_HPP diff --git a/include/sta/assert.hpp b/include/sta/debug/assert.hpp similarity index 100% rename from include/sta/assert.hpp rename to include/sta/debug/assert.hpp diff --git a/include/sta/debug/debug.hpp b/include/sta/debug/debug.hpp new file mode 100644 index 0000000..0396ea1 --- /dev/null +++ b/include/sta/debug/debug.hpp @@ -0,0 +1,40 @@ +#ifndef STA_CORE_DEBUGGING_HPP +#define STA_CORE_DEBUGGING_HPP + +#include +#ifdef STA_DEBUGGING_ENABLED + +#include + +namespace sta +{ + extern Printable * Debug; +} // namespace sta + + +/** + * @brief Debug print message. + * + * @param ... See @ref sta::PrintableUART::print + * + * @ingroup sta_core_debug + */ +# define STA_DEBUG_PRINT(...) sta::Debug->print(__VA_ARGS__) + +/** + * @brief Debug print message followed by new-line to UART. + * + * @param ... See @ref sta::PrintableUART::println + * + * @ingroup sta_core_debug + */ +# define STA_DEBUG_PRINTLN(...) sta::Debug->println(__VA_ARGS__) + +#else // !STA_DEBUGGING_ENABLED + +# define STA_DEBUG_PRINT(...) ((void)0) +# define STA_DEBUG_PRINTLN(...) ((void)0) + +#endif // STA_DEBUGGING_ENABLED + +#endif // STA_CORE_DEBUGGING_HPP diff --git a/include/sta/printable_uart.hpp b/include/sta/debug/printing/printable.hpp similarity index 84% rename from include/sta/printable_uart.hpp rename to include/sta/debug/printing/printable.hpp index d5473fc..77117a3 100644 --- a/include/sta/printable_uart.hpp +++ b/include/sta/debug/printing/printable.hpp @@ -2,10 +2,8 @@ * @file * @brief Printable UART interface definition. */ -#ifndef STA_CORE_PRINTABLE_UART_HPP -#define STA_CORE_PRINTABLE_UART_HPP - -#include +#ifndef STA_CORE_PRINTABLE_HPP +#define STA_CORE_PRINTABLE_HPP #include #include @@ -25,37 +23,30 @@ namespace sta HEX /**< Hexadecimal */ }; - /** - * @brief Printable interface for UART. - * - * @ingroup sta_core - */ - class PrintableUART + class Printable { public: - /** - * @param intf UART instance - */ - PrintableUART(UART * intf); - /** * @brief Print single character. * * @param c Character to print */ void print(char c); + /** * @brief Print boolean value. * * @param b Boolean value */ void print(bool b); + /** * @brief Print floating point value. * * @param d Floating point value */ void print(double d); + /** * @brief Print integer in selected base. * @@ -63,6 +54,7 @@ namespace sta * @param base Integer base */ void print(uint8_t num, IntegerBase base = IntegerBase::DEC); + /** * @brief Print integer in selected base. * @@ -70,6 +62,7 @@ namespace sta * @param base Integer base */ void print(uint16_t num, IntegerBase base = IntegerBase::DEC); + /** * @brief Print integer in selected base. * @@ -77,50 +70,48 @@ namespace sta * @param base Integer base */ void print(uint32_t num, IntegerBase base = IntegerBase::DEC); - /** - * @brief Print integer in selected base. - * - * @param num Integer - * @param base Integer base - */ - void print(size_t num, IntegerBase base = IntegerBase::DEC); + /** * @brief Print c-string. * * @param str Null terminated string */ void print(const char * str); + /** * @brief Print string. * * @param str String buffer * @param length String length */ - void print(const char * str, size_t length); - + virtual void print(const char * str, size_t length) = 0; /** * @brief Print new-line. */ void println(); + /** * @brief Print single character followed by a new-line. * * @param c Character to print */ void println(char c); + /** * @brief Print boolean value followed by a new-line. * * @param b Boolean value */ void println(bool b); + /** * @brief Print floating point value followed by a new-line. * * @param d Floating point value */ void println(double d); + /** * @brief Print integer in selected base followed by a new-line. * @@ -128,6 +119,7 @@ namespace sta * @param base Integer base */ void println(uint8_t num, IntegerBase base = IntegerBase::DEC); + /** * @brief Print integer in selected base followed by a new-line. * @@ -135,6 +127,7 @@ namespace sta * @param base Integer base */ void println(uint16_t num, IntegerBase base = IntegerBase::DEC); + /** * @brief Print integer in selected base followed by a new-line. * @@ -142,19 +135,14 @@ namespace sta * @param base Integer base */ void println(uint32_t num, IntegerBase base = IntegerBase::DEC); - /** - * @brief Print integer in selected base followed by a new-line. - * - * @param num Integer - * @param base Integer base - */ - void println(size_t num, IntegerBase base = IntegerBase::DEC); + /** * @brief Print c-string followed by a new-line. * * @param str Null terminated string */ void println(const char * str); + /** * @brief Print string followed by a new-line. * @@ -173,6 +161,7 @@ namespace sta * @param size Size of value in bytes */ void printBase(uintmax_t value, IntegerBase base, const char * fmt, size_t size); + /** * @brief Print unsigned integer in base 10. * @@ -180,6 +169,7 @@ namespace sta * @param fmt printf format string */ void printDec(uintmax_t value, const char * fmt); + /** * @brief Print unsigned integer in base 2. * @@ -187,6 +177,7 @@ namespace sta * @param digits Number of digits to print */ void printBin(uintmax_t value, size_t digits); + /** * @brief Print unsigned integer in base 16. * @@ -194,11 +185,8 @@ namespace sta * @param digits Number of digits to print */ void printHex(uintmax_t value, size_t digits); - - private: - UART * intf_; }; } // namespace sta -#endif // STA_CORE_PRINTABLE_UART_HPP +#endif // STA_CORE_PRINTABLE_HPP diff --git a/include/sta/debug/printing/printable_printf.hpp b/include/sta/debug/printing/printable_printf.hpp new file mode 100644 index 0000000..2ef9ed6 --- /dev/null +++ b/include/sta/debug/printing/printable_printf.hpp @@ -0,0 +1,26 @@ +#ifndef STA_CORE_PRINTABLE_PRINTF_HPP +#define STA_CORE_PRINTABLE_PRINTF_HPP + +#include + +namespace sta +{ + class PrintablePrintf : public Printable + { + public: + /** + * @brief Construct a new Printable Printf object + */ + PrintablePrintf(); + + /** + * @brief Print string. + * + * @param str String buffer + * @param length String length + */ + void print(const char * str, size_t length) override; + }; +} // namespace sta + +#endif // STA_CORE_PRINTABLE_PRINTF_HPP \ No newline at end of file diff --git a/include/sta/debug/printing/printable_uart.hpp b/include/sta/debug/printing/printable_uart.hpp new file mode 100644 index 0000000..93f92c5 --- /dev/null +++ b/include/sta/debug/printing/printable_uart.hpp @@ -0,0 +1,44 @@ +/** + * @file + * @brief Printable UART interface definition. + */ +#ifndef STA_CORE_PRINTABLE_UART_HPP +#define STA_CORE_PRINTABLE_UART_HPP + +#include +#include + +#include +#include + + +namespace sta +{ + /** + * @brief Printable interface for UART. + * + * @ingroup sta_core + */ + class PrintableUART : public Printable + { + public: + /** + * @param intf UART instance + */ + PrintableUART(UART * intf); + + /** + * @brief Print string. + * + * @param str String buffer + * @param length String length + */ + void print(const char * str, size_t length) override; + + private: + UART * intf_; + }; +} // namespace sta + + +#endif // STA_CORE_PRINTABLE_UART_HPP diff --git a/include/sta/debug_serial.hpp b/include/sta/debug_serial.hpp deleted file mode 100644 index ee3bd11..0000000 --- a/include/sta/debug_serial.hpp +++ /dev/null @@ -1,79 +0,0 @@ -/** - * @file - * @brief Debug output via UART. - * - * Configuration: - * * STA_DEBUG_SERIAL_UART: UART interface for output - * * STA_DEBUG_SERIAL_FORCE: Ignore debug defines and always enable output - * * DEBUG: Enables output when defined - * * NDEBUG: Disables output when defined (overrides DEBUG) - */ -#ifndef STA_CORE_DEBUG_SERIAL_HPP -#define STA_CORE_DEBUG_SERIAL_HPP - - -#include - -// Determine if module should be enabled -// Condition 1: STA_DEBUG_SERIAL_UART is defined -// Condition 2: -// STA_DEBUG_SERIAL_FORCE is defined -// or -// DEBUG is defined but not NDEBUG -#ifdef STA_DEBUG_SERIAL_UART -# ifdef STA_DEBUG_SERIAL_FORCE -# define STA_DEBUG_SERIAL_ENABLED -# else // !STA_DEBUG_SERIAL_FORCE -# if defined(DEBUG) && !defined(NDEBUG) -# define STA_DEBUG_SERIAL_ENABLED -# endif // DEBUG && !NDEBUG -# endif // !STA_DEBUG_SERIAL_FORCE -#endif // STA_DEBUG_SERIAL_UART - - -#if defined(STA_DEBUG_SERIAL_ENABLED) || defined(DOXYGEN) - -#include - - -/** - * @defgroup sta_core_debug Debug Serial - * @ingroup sta_core - * @brief Debug serial output. - */ - - -namespace sta -{ - /** - * @brief %UART print object for debug serial output. - * - * @ingroup sta_core_debug - */ - extern PrintableUART DebugSerial; -} // namespace sta - - -/** - * @brief Print debug output to UART. - * - * @param ... See @ref sta::PrintableUART::print - * - * @ingroup sta_core_debug - */ -# define STA_DEBUG_PRINT(...) sta::DebugSerial.print(__VA_ARGS__) -/** - * @brief Print debug output followed by new-line to UART. - * - * @param ... See @ref sta::PrintableUART::println - * - * @ingroup sta_core_debug - */ -# define STA_DEBUG_PRINTLN(...) sta::DebugSerial.println(__VA_ARGS__) -#else // !STA_DEBUG_SERIAL_ENABLED -# define STA_DEBUG_PRINT(...) ((void)0) -# define STA_DEBUG_PRINTLN(...) ((void)0) -#endif // !STA_DEBUG_SERIAL_ENABLED - - -#endif // STA_CORE_DEBUG_SERIAL_HPP diff --git a/include/sta/devices/arduino/bus/i2c.hpp b/include/sta/devices/arduino/bus/i2c.hpp new file mode 100644 index 0000000..ff9a4e9 --- /dev/null +++ b/include/sta/devices/arduino/bus/i2c.hpp @@ -0,0 +1,36 @@ +#ifndef STA_CORE_ARDUINO_I2C_HPP +#define STA_CORE_ARDUINO_I2C_HPP + +#include +#ifdef STA_PLATFORM_ARDUINO + +#include +#include + +namespace sta +{ + class ArduinoI2C : public I2C + { + public: + ArduinoI2C(Mutex * mutex=nullptr, uint16_t address); + + void transfer16(uint16_t value) override; + void transfer(const uint8_t * buffer, size_t size) override; + void transfer(const uint8_t * txBuffer, uint8_t * rxBuffer, size_t size) override; + void receive(uint8_t * buffer, size_t size) override; + void fill(uint8_t value, size_t count) override; + + void acquire(); + void release(); + }; + + class ArduinoI2CDevice : public I2CDevice + { + public: + ArduinoI2CDevice(I2C * intf, int address, bool master=false, bool blocking=true); + }; +} // namespace sta + +#endif // STA_PLATFORM_ARDUINO + +#endif // STA_CORE_ARDUINO_I2C_HPP \ No newline at end of file diff --git a/include/sta/devices/arduino/bus/spi.hpp b/include/sta/devices/arduino/bus/spi.hpp new file mode 100644 index 0000000..e69de29 diff --git a/include/sta/devices/arduino/delay.hpp b/include/sta/devices/arduino/delay.hpp new file mode 100644 index 0000000..bcc6ebb --- /dev/null +++ b/include/sta/devices/arduino/delay.hpp @@ -0,0 +1,28 @@ +#ifndef STA_CORE_ARDUINO_DELAY_HPP +#define STA_CORE_ARDUINO_DELAY_HPP + +// Only enable module on Arduino platform +#include + +#if defined(STA_PLATFORM_ARDUINO) || defined(DOXYGEN) + +namespace sta +{ + /** + * @brief Millisecond delay. + * + * @param ms Milliseconds + */ + void delayMs(uint32_t ms); + + /** + * @brief Microsecond delay. + * + * @param us Microseconds + */ + void delayUs(uint32_t us); +} // namespace sta + +#endif // STA_PLATFORM_ARDUINO + +#endif // STA_CORE_ARDUINO_DELAY_HPP \ No newline at end of file diff --git a/include/sta/devices/arduino/gpio_pin.hpp b/include/sta/devices/arduino/gpio_pin.hpp new file mode 100644 index 0000000..dd03289 --- /dev/null +++ b/include/sta/devices/arduino/gpio_pin.hpp @@ -0,0 +1,44 @@ +/** + * @file + * @brief Wrapper for Arduino GPIO pins. + */ +#ifndef STA_CORE_ARDUINO_GPIO_PIN_HPP +#define STA_CORE_ARDUINO_GPIO_PIN_HPP + +// Only enable module on Arduino platform w/ HAL GPIO module enabled +#include + +#if defined(STA_PLATFORM_ARDUINO) || defined(DOXYGEN) + +#include +#include + +namespace sta +{ + class ArduinoGpioPin : public GpioPin + { + public: + /** + * @param port GPIO port + * @param pin Pin index + */ + ArduinoGpioPin(uint16_t pin); + + void setState(GpioPinState state) override; + + GpioPinState getState() override; + + /** + * @brief Get pin index for pin. + * + * @return Pin index + */ + uint16_t getPin() const; + private: + uint16_t pin_; /**< GPIO pin */ + }; +} // namespace sta + +#endif // STA_ARDUINO_GPIO_ENABLED + +#endif // STA_CORE_ARDUINO_GPIO_PIN_HPP \ No newline at end of file diff --git a/include/sta/devices/arduino/hal.hpp b/include/sta/devices/arduino/hal.hpp new file mode 100644 index 0000000..1693555 --- /dev/null +++ b/include/sta/devices/arduino/hal.hpp @@ -0,0 +1,8 @@ +#ifndef STA_CORE_ARDUINO_HAL_HPP +#define STA_CORE_ARDUINO_HAL_HPP + +#include +#include +#include + +#endif // STA_CORE_ARDUINO_HAL_HPP \ No newline at end of file diff --git a/include/sta/devices/arduino/mcu/common.hpp b/include/sta/devices/arduino/mcu/common.hpp new file mode 100644 index 0000000..3a79c10 --- /dev/null +++ b/include/sta/devices/arduino/mcu/common.hpp @@ -0,0 +1,7 @@ +#ifndef STA_CORE_ARDUINO_MCU_COMMON_HPP +#define STA_CORE_ARDUINO_MCU_COMMON_HPP + +// Enable Arduino platform +#define STA_PLATFORM_ARDUINO + +#endif // STA_CORE_ARDUINO_MCU_COMMON_HPP \ No newline at end of file diff --git a/include/sta/devices/arduino/mcu/uno_r3.hpp b/include/sta/devices/arduino/mcu/uno_r3.hpp new file mode 100644 index 0000000..a367296 --- /dev/null +++ b/include/sta/devices/arduino/mcu/uno_r3.hpp @@ -0,0 +1,6 @@ +#ifndef STA_CORE_ARDUINO_MCU_UNO_R3_HPP +#define STA_CORE_ARDUINO_MCU_UNO_R3_HPP + +#include + +#endif // STA_CORE_ARDUINO_MCU_UNO_R3_HPPs \ No newline at end of file diff --git a/include/sta/devices/raspi/bus/i2c.hpp b/include/sta/devices/raspi/bus/i2c.hpp new file mode 100644 index 0000000..5e9d6a5 --- /dev/null +++ b/include/sta/devices/raspi/bus/i2c.hpp @@ -0,0 +1,52 @@ +#ifndef STA_RASPI_I2C_HPP +#define STA_RASPI_I2C_HPP + +#include +#ifdef STA_PLATFORM_RASPI + +#include +#include + +#include +#include + +namespace sta +{ + enum class I2CNode { + DEV_1, + DEV_2 + }; + + class RaspiI2C : public I2C + { + public: + RaspiI2C(I2CNode node, Mutex * mutex=nullptr, bool persistent_open=false); + ~RaspiI2C(); + + void transfer(uint8_t value) override; + void transfer16(uint16_t value) override; + void transfer(const uint8_t * buffer, size_t size) override; + void receive(uint8_t * buffer, size_t size) override; + + void selectAddress(); + void acquire() override; + void release() override; + + void fill(uint8_t value, size_t count) override; + private: + char * i2cdev_; + int i2cfd_; + bool open_ = false; + const bool persistent_open_; + }; + + class RaspiI2CDevice : public I2CDevice + { + public: + RaspiI2CDevice(RaspiI2C * intf, uint16_t address_10bit, bool master=true, bool blocking=true); + }; +} // namespace sta + +#endif // STA_PLATFORM_RASPI + +#endif // STA_I2C_HPP diff --git a/include/sta/devices/raspi/bus/spi.hpp b/include/sta/devices/raspi/bus/spi.hpp new file mode 100644 index 0000000..266a0cc --- /dev/null +++ b/include/sta/devices/raspi/bus/spi.hpp @@ -0,0 +1,60 @@ +#ifndef STA_CORE_RASPI_SPI_HPP +#define STA_CORE_RASPI_SPI_HPP + +#include +#ifdef STA_PLATFORM_RASPI + +#include +#include + +namespace sta +{ + enum class SPINode { + DEV_0_0, + DEV_0_1 + }; + + class RaspiSPI : public SPI + { + public: + RaspiSPI(SPINode node, const SPISettings & settings, Mutex * mutex = nullptr, bool persistent_open = true); + ~RaspiSPI(); + + void transfer(uint8_t value) override; + void transfer16(uint16_t value) override; + void transfer(const uint8_t * buffer, size_t size) override; + void transfer(const uint8_t * txBuffer, uint8_t * rxBuffer, size_t size) override; + void receive(uint8_t * buffer, size_t size) override; + + void fill(uint8_t value, size_t count) override; + + void acquire() override; + void release() override; + + private: + char * spidev_; + int spifd_; + bool open_; + const bool persistent_open_; + SPISettings settings_; + + uint8_t mode_; + uint8_t dataSize_; + uint8_t bitOrder_; + uint32_t clkSpeed_; + + void update_setting(int setting, int value); + void get_setting(int setting, void * rslt_ptr); + void update_settings(); + }; + + class RaspiSPIDevice : public SPIDevice + { + public: + RaspiSPIDevice(RaspiSPI * intf); + }; +} // namespace sta + +#endif // STA_PLATFORM_RASPI + +#endif // STA_CORE_RASPI_HPP \ No newline at end of file diff --git a/include/sta/devices/raspi/can.hpp b/include/sta/devices/raspi/can.hpp new file mode 100644 index 0000000..e69de29 diff --git a/include/sta/devices/raspi/delay.hpp b/include/sta/devices/raspi/delay.hpp new file mode 100644 index 0000000..cbf85dc --- /dev/null +++ b/include/sta/devices/raspi/delay.hpp @@ -0,0 +1,44 @@ +/** + * @file + * @brief Delay functions. + * + * Configuration: + * * STA_RASPI_DELAY_US_TIM: 1 MHz TIM instance used by sta::delayUs + * + * NOTE: TIM time base must be started before use of sta::delayUs by calling sta::initHAL. + * When using startup system task this is handled automatically. + */ +#ifndef STA_CORE_RASPI_DELAY_HPP +#define STA_CORE_RASPI_DELAY_HPP + + +// Only enable module on RASPI platform +#include + + +#if defined(STA_PLATFORM_RASPI) || defined(DOXYGEN) + +#include + + +namespace sta +{ + /** + * @brief Millisecond delay. + * + * @param ms Milliseconds + */ + void delayMs(uint32_t ms); + + /** + * @brief Microsecond delay. + * + * @param us Microseconds + */ + void delayUs(uint32_t us); +} // namespace sta + + +#endif // STA_PLATFORM_RASPI + +#endif // STA_CORE_RASPI_DELAY_HPP diff --git a/include/sta/devices/raspi/gpio_pin.hpp b/include/sta/devices/raspi/gpio_pin.hpp new file mode 100644 index 0000000..22af920 --- /dev/null +++ b/include/sta/devices/raspi/gpio_pin.hpp @@ -0,0 +1,46 @@ +#ifndef STA_CORE_RASPI_GPIO_PIN_HPP +#define STA_CORE_RASPI_GPIO_PIN_HPP + +// Only enable module on Raspi platform w/ HAL GPIO module enabled +#include +#ifdef STA_PLATFORM_RASPI +# include +# define STA_RASPI_GPIO_ENABLED +#endif // STA_PLATFORM_RASPI + +#if defined(STA_RASPI_GPIO_ENABLED) || defined(DOXYGEN) + +#include +#include + +namespace sta +{ + enum class GpioMode { + GPIO_OUTPUT, + GPIO_INPUT + }; + + class RaspiGpioPin : public GpioPin + { + public: + /** + * @param pin Pin index + * @param mode The mode of the GPIO pin. Either INPUT or OUTPUT + */ + RaspiGpioPin(uint8_t pin, GpioMode mode); + + void setState(GpioPinState state) override; + + GpioPinState getState() override; + + static RaspiGpioPin * DUMMY_GPIO; + + private: + uint8_t pin_; + GpioMode mode_; + }; +} // namespace sta + +#endif // STA_RASPI_GPIO_ENABLED + +#endif // STA_CORE_RASPI_GPIO_PIN_HPP \ No newline at end of file diff --git a/include/sta/devices/raspi/hal.hpp b/include/sta/devices/raspi/hal.hpp new file mode 100644 index 0000000..112597c --- /dev/null +++ b/include/sta/devices/raspi/hal.hpp @@ -0,0 +1,8 @@ +#ifndef STA_CORE_RASPI_HAL_HPP +#define STA_CORE_RASPI_HAL_HPP + +#include +#include +#include + +#endif //STA_CORE_RASPI_HAL_HPP diff --git a/include/sta/devices/raspi/mcu/common.hpp b/include/sta/devices/raspi/mcu/common.hpp new file mode 100644 index 0000000..89ce60f --- /dev/null +++ b/include/sta/devices/raspi/mcu/common.hpp @@ -0,0 +1,13 @@ +/** + * @file + * @brief Common configuration for Raspberry Pi MCUs + */ +#ifndef STA_CORE_RASPI_MCU_COMMON_HPP +#define STA_CORE_RASPI_MCU_COMMON_HPP + +#define STA_MCU_LITTLE_ENDIAN + +// Enable STM32 platform +#define STA_PLATFORM_RASPI + +#endif // STA_CORE_RASPI_MCU_COMMON_HPP \ No newline at end of file diff --git a/include/sta/devices/stm32/adc.hpp b/include/sta/devices/stm32/adc.hpp new file mode 100644 index 0000000..c04e2c6 --- /dev/null +++ b/include/sta/devices/stm32/adc.hpp @@ -0,0 +1,44 @@ +#ifndef STA_CORE_STM32_ADC_HPP +#define STA_CORE_STM32_ADC_HPP + +#include +#ifdef STA_PLATFORM_STM32 +# include +# ifdef HAL_ADC_MODULE_ENABLED +# define STA_STM32_ADC_ENABLED +# endif +#endif + +#if defined(STA_STM32_ADC_ENABLED) || defined(DOXYGEN) + +namespace sta +{ + class STM32ADC + { + public: + /** + * @param handle A handle to a STM32 ADC. + */ + STM32ADC(ADC_HandleTypeDef * handle); + + /** + * @brief Starts conversion of the incoming analog signal. + */ + void start(); + + /** + * @brief + * + * @param timeout + */ + void poll(uint32_t timeout); + + uint32_t getValue(); + private: + ADC_HandleTypeDef * handle_; + }; +} // namespace sta + +#endif // STA_STM32_ADC_ENABLED + +#endif // STA_CORE_STM32_ADC_HPP diff --git a/include/sta/devices/stm32/bus/i2c.hpp b/include/sta/devices/stm32/bus/i2c.hpp new file mode 100644 index 0000000..c195709 --- /dev/null +++ b/include/sta/devices/stm32/bus/i2c.hpp @@ -0,0 +1,44 @@ +#ifndef STA_CORE_STM32_I2C_HPP +#define STA_CORE_STM32_I2C_HPP + +#include +#ifdef STA_PLATFORM_STM32 +# include +# ifdef HAL_I2C_MODULE_ENABLED +# define STA_STM32_I2C_ENABLED +# endif // HAL_SPI_MODULE_ENABLED +#endif // STA_PLATFORM_STM32 + +#ifdef STA_STM32_I2C_ENABLED + +#include +#include + +namespace sta +{ + class STM32I2C : public I2C + { + public: + STM32I2C(I2C_HandleTypeDef * handle, Mutex * mutex=nullptr); + + void transfer(uint8_t value) override; + void transfer16(uint16_t value) override; + void transfer(const uint8_t * buffer, size_t size) override; + void receive(uint8_t * buffer, size_t size) override; + + void fill(uint8_t value, size_t count) override; + private: + I2C_HandleTypeDef * handle_; + const uint32_t timeout_ = 1000; + }; + + class STM32I2CDevice : public I2CDevice + { + public: + STM32I2CDevice(STM32I2C * intf, int address, bool master=true, bool blocking=true); + }; +} + +#endif // STA_STM32_I2C_ENABLED + +#endif // STA_CORE_STM32_I2C_HPP diff --git a/include/sta/stm32/spi.hpp b/include/sta/devices/stm32/bus/spi.hpp similarity index 92% rename from include/sta/stm32/spi.hpp rename to include/sta/devices/stm32/bus/spi.hpp index 0e477bf..9ed1ee0 100644 --- a/include/sta/stm32/spi.hpp +++ b/include/sta/devices/stm32/bus/spi.hpp @@ -9,7 +9,7 @@ // Only enable module on STM32 platform w/ HAL SPI module enabled #include #ifdef STA_PLATFORM_STM32 -# include +# include # ifndef HAL_GPIO_MODULE_ENABLED # error "STM32 GPIO module required!" # endif // !HAL_GPIO_MODULE_ENABLED @@ -21,11 +21,11 @@ #if defined(STA_STM32_SPI_ENABLED) || defined(DOXYGEN) -#include -#include +#include +#include -#include -#include +#include +#include /** @@ -92,10 +92,7 @@ namespace sta * @param intf %SPI interface * @param csPin Device CS pin */ - STM32SPIDevice(STM32SPI * intf, STM32GpioPin csPin); - - private: - STM32GpioPin csPin_; /**< Device CS pin */ + STM32SPIDevice(STM32SPI * intf, STM32GpioPin * csPin); }; diff --git a/include/sta/stm32/uart.hpp b/include/sta/devices/stm32/bus/uart.hpp similarity index 69% rename from include/sta/stm32/uart.hpp rename to include/sta/devices/stm32/bus/uart.hpp index fb1a10e..5982c8b 100644 --- a/include/sta/stm32/uart.hpp +++ b/include/sta/devices/stm32/bus/uart.hpp @@ -9,7 +9,7 @@ // Only enable module on STM32 platform w/ HAL UART module enabled #include #ifdef STA_PLATFORM_STM32 -# include +# include # ifdef HAL_UART_MODULE_ENABLED # define STA_STM32_UART_ENABLED # endif // HAL_UART_MODULE_ENABLED @@ -18,7 +18,7 @@ #if defined(STA_STM32_UART_ENABLED) || defined(DOXYGEN) -#include +#include /** @@ -41,10 +41,14 @@ namespace sta /** * @param handle STM32 HAL handle */ - STM32UART(UART_HandleTypeDef * handle); + STM32UART(UART_HandleTypeDef * handle, UARTSettings & settings, Mutex * mutex); - void write(const uint8_t * buffer, size_t size) override; + void transfer(uint8_t value) override; + void transfer16(uint16_t value) override; + void transfer(const uint8_t * buffer, size_t size) override; + void receive(uint8_t * buffer, size_t size) override; + void fill(uint8_t value, size_t count) override; private: UART_HandleTypeDef * handle_; /**< STM32 HAL handle */ }; diff --git a/include/sta/stm32/can.hpp b/include/sta/devices/stm32/can.hpp similarity index 97% rename from include/sta/stm32/can.hpp rename to include/sta/devices/stm32/can.hpp index 2bf910c..95a96c5 100644 --- a/include/sta/stm32/can.hpp +++ b/include/sta/devices/stm32/can.hpp @@ -19,7 +19,7 @@ // Only enable module on STM32 platform w/ HAL CAN module enabled #include #ifdef STA_PLATFORM_STM32 -# include +# include # ifdef HAL_CAN_MODULE_ENABLED # define STA_STM32_CAN_ENABLED # endif // HAL_CAN_MODULE_ENABLED @@ -28,7 +28,7 @@ #if defined(STA_STM32_CAN_ENABLED) || defined(DOXYGEN) -#include +#include namespace sta diff --git a/include/sta/stm32/clocks.hpp b/include/sta/devices/stm32/clocks.hpp similarity index 98% rename from include/sta/stm32/clocks.hpp rename to include/sta/devices/stm32/clocks.hpp index a556fb5..df4604e 100644 --- a/include/sta/stm32/clocks.hpp +++ b/include/sta/devices/stm32/clocks.hpp @@ -12,7 +12,7 @@ #if defined(STA_PLATFORM_STM32) || defined(DOXYGEN) -#include +#include /** diff --git a/include/sta/devices/stm32/dac.hpp b/include/sta/devices/stm32/dac.hpp new file mode 100644 index 0000000..e85ec5b --- /dev/null +++ b/include/sta/devices/stm32/dac.hpp @@ -0,0 +1,17 @@ +#ifndef STA_CORE_STM32_DAC_HPP +#define STA_CORE_STM32_DAC_HPP + +#include +#ifdef STA_PLATFORM_STM32 + +namespace sta +{ + class DAC + { + + }; +} // namespace sta + +#endif // STA_PLATFORM_STM32 + +#endif // STA_CORE_STM32_DAC_HPP \ No newline at end of file diff --git a/include/sta/stm32/delay.hpp b/include/sta/devices/stm32/delay.hpp similarity index 100% rename from include/sta/stm32/delay.hpp rename to include/sta/devices/stm32/delay.hpp diff --git a/include/sta/stm32/gpio_pin.hpp b/include/sta/devices/stm32/gpio_pin.hpp similarity index 96% rename from include/sta/stm32/gpio_pin.hpp rename to include/sta/devices/stm32/gpio_pin.hpp index f6f355e..205b297 100644 --- a/include/sta/stm32/gpio_pin.hpp +++ b/include/sta/devices/stm32/gpio_pin.hpp @@ -9,7 +9,7 @@ // Only enable module on STM32 platform w/ HAL GPIO module enabled #include #ifdef STA_PLATFORM_STM32 -# include +# include # ifdef HAL_GPIO_MODULE_ENABLED # define STA_STM32_GPIO_ENABLED # endif // HAL_GPIO_MODULE_ENABLED @@ -50,6 +50,8 @@ namespace sta void setState(GpioPinState state) override; + GpioPinState getState() override; + /** * @brief Get GPIO port for pin. * diff --git a/include/sta/stm32/hal.hpp b/include/sta/devices/stm32/hal.hpp similarity index 100% rename from include/sta/stm32/hal.hpp rename to include/sta/devices/stm32/hal.hpp diff --git a/include/sta/stm32/init.hpp b/include/sta/devices/stm32/init.hpp similarity index 100% rename from include/sta/stm32/init.hpp rename to include/sta/devices/stm32/init.hpp diff --git a/include/sta/stm32/mcu/STM32F411xE.hpp b/include/sta/devices/stm32/mcu/STM32F411xE.hpp similarity index 98% rename from include/sta/stm32/mcu/STM32F411xE.hpp rename to include/sta/devices/stm32/mcu/STM32F411xE.hpp index 838408d..cdca7c2 100644 --- a/include/sta/stm32/mcu/STM32F411xE.hpp +++ b/include/sta/devices/stm32/mcu/STM32F411xE.hpp @@ -11,7 +11,7 @@ #endif // !STM32F411xE -#include +#include // Peripheral clock mappings diff --git a/include/sta/stm32/mcu/STM32F413xx.hpp b/include/sta/devices/stm32/mcu/STM32F413xx.hpp similarity index 100% rename from include/sta/stm32/mcu/STM32F413xx.hpp rename to include/sta/devices/stm32/mcu/STM32F413xx.hpp diff --git a/include/sta/stm32/mcu/common.hpp b/include/sta/devices/stm32/mcu/common.hpp similarity index 100% rename from include/sta/stm32/mcu/common.hpp rename to include/sta/devices/stm32/mcu/common.hpp diff --git a/include/sta/devices/template/custom_printable.hpp b/include/sta/devices/template/custom_printable.hpp new file mode 100644 index 0000000..594ba31 --- /dev/null +++ b/include/sta/devices/template/custom_printable.hpp @@ -0,0 +1,34 @@ +#ifndef STA_CORE_YOUR_DEVICE_CUSTOM_PRINTABLE_HPP +#define STA_CORE_YOUR_DEVICE_CUSTOM_PRINTABLE_HPP + +#include + +#if defined(STA_PLATFORM_YOUR_DEVICE) || defined(DOXYGEN) + +#include + +namespace sta +{ + class CustomPrintable : public Printable + { + public: + /** + * @brief Constructor for your custom printable. + * + * Delete if not needed. + */ + CustomPrintable(/* YOUR ARGMENTS */); + + /** + * @brief Print string. + * + * @param str String buffer + * @param length String length + */ + void print(const char * str, size_t length) override; + }; +} // namespace sta + +#endif // STA_PLATFORM_YOUR_DEVICE + +#endif // STA_CORE_YOUR_DEVICE_CUSTOM_PRINTABLE_HPP \ No newline at end of file diff --git a/include/sta/devices/template/delay.hpp b/include/sta/devices/template/delay.hpp new file mode 100644 index 0000000..a87bd66 --- /dev/null +++ b/include/sta/devices/template/delay.hpp @@ -0,0 +1,43 @@ +/** + * @file delay.hpp + * @author (@.com) + * @brief + * @version 0.1 + * @date 2023-06-13 + * + * @copyright Copyright (c) 2023 + * + * How to modify this file: + * - Ctrl + F and replace "YOUR_DEVICE" with the appropriate name. + */ +#ifndef STA_CORE_YOUR_DEVICE_DELAY_HPP +#define STA_CORE_YOUR_DEVICE_DELAY_HPP + +// Only enable module on YOUR_DEVICE platform +#include + + +#if defined(STA_PLATFORM_YOUR_DEVICE) || defined(DOXYGEN) + +#include + +namespace sta +{ + /** + * @brief Millisecond delay. + * + * @param ms Milliseconds + */ + void delayMs(uint32_t ms); + + /** + * @brief Microsecond delay. + * + * @param us Microseconds + */ + void delayUs(uint32_t us); +} // namespace sta + +#endif // STA_PLATFORM_YOUR_DEVICE + +#endif // STA_CORE_YOUR_DEVICE_DELAY_HPP \ No newline at end of file diff --git a/include/sta/gpio_pin.hpp b/include/sta/gpio_pin.hpp index 82ce7ec..9a26f4c 100644 --- a/include/sta/gpio_pin.hpp +++ b/include/sta/gpio_pin.hpp @@ -21,8 +21,8 @@ namespace sta */ enum class GpioPinState { - LOW, - HIGH + GPIO_LOW, + GPIO_HIGH }; /** @@ -37,6 +37,13 @@ namespace sta * @param state Output state */ virtual void setState(GpioPinState state) = 0; + + /** + * @brief Get pin input state. + * + * @param state Input state + */ + virtual GpioPinState getState() = 0; }; diff --git a/include/sta/i2c.hpp b/include/sta/i2c.hpp deleted file mode 100644 index db467dd..0000000 --- a/include/sta/i2c.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef STA_I2C_HPP -#define STA_I2C_HPP - -#include -#include - -namespace sta { - class I2cDevice { - protected: - uint16_t address; - Mutex* mutex; - bool master; - bool blocking; - public: - I2cDevice(uint16_t address_10bit, Mutex* mutex=nullptr, bool master=false, bool blocking=true); - - virtual bool transmit(uint8_t* data, uint16_t size) = 0; - - virtual bool receive(uint8_t* data, uint16_t size) = 0; - - virtual void acquire(); - - virtual void release(); - }; -} - -#endif // STA_I2C_HPP diff --git a/include/sta/lang.hpp b/include/sta/lang.hpp index 35591b7..037823f 100644 --- a/include/sta/lang.hpp +++ b/include/sta/lang.hpp @@ -95,6 +95,14 @@ # define STA_UNREACHABLE() __builtin_unreachable() #endif // !STA_UNREACHABLE +/** + * @brief A macro for marking code as not implemented. Causes a program to + * crash with the appropriate error message if the code is executed. + */ +#ifndef STA_NOT_IMPLEMENTED +# define STA_NOT_IMPLEMENTED() // throw "myFunction is not implemented yet."; +#endif // !STA_NOT_IMPLEMENTED + /** * @brief Silencing compiler warnings for intended switch case fallthrough. * diff --git a/include/sta/stm32/i2c.hpp b/include/sta/stm32/i2c.hpp deleted file mode 100644 index 4804e1a..0000000 --- a/include/sta/stm32/i2c.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef STA_STM32_I2C_HPP -#define STA_STM32_I2C_HPP - -#include -#ifdef STA_PLATFORM_STM32 -# include -# ifdef HAL_I2C_MODULE_ENABLED -# define STA_STM32_I2C_ENABLED -# endif // HAL_SPI_MODULE_ENABLED -#endif // STA_PLATFORM_STM32 - -#ifdef STA_STM32_I2C_ENABLED - -#include - -namespace sta { - class STM32I2cDevice : public I2cDevice { - private: - I2C_HandleTypeDef* i2cHandle; - const uint32_t timeout = HAL_MAX_DELAY; - - public: - STM32I2cDevice( - I2C_HandleTypeDef* i2cHandle, - uint16_t address, - Mutex* mutex=nullptr, - bool master=false, - bool blocking=true - ); - - bool transmit(uint8_t* data, uint16_t size) override; - bool receive(uint8_t* data, uint16_t size) override; - - bool deviceReady(); - }; -} - -#endif // STA_STM32_I2C_ENABLED -#endif // STA_STM32_I2C_HPP diff --git a/include/sta/uart.hpp b/include/sta/uart.hpp deleted file mode 100644 index 9667623..0000000 --- a/include/sta/uart.hpp +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @file - * @brief UART interface definition. - */ -#ifndef STA_CORE_UART_HPP -#define STA_CORE_UART_HPP - -#include -#include - - -/** - * @defgroup sta_core_uart UART - * @ingroup sta_core - * @brief UART interface. - */ - - -namespace sta -{ - /** - * @brief Interface for %UART. - * - * @ingroup sta_core_uart - */ - class UART - { - public: - /** - * @brief Write buffer to %UART. - * - * @param buffer Source buffer - * @param size Number of bytes in buffer - */ - virtual void write(const uint8_t * buffer, size_t size) = 0; - - /** - * @brief Write unsigned integer to %UART. - * - * @param value Unsigned integer value - */ - void write(uint8_t value); - /** - * @brief Write unsigned integer to %UART. - * - * @param value Unsigned integer value - */ - void write(uint16_t value); - /** - * @brief Write unsigned integer to %UART. - * - * @param value Unsigned integer value - */ - void write(uint32_t value); - }; -} // namespace sta - - -#endif // STA_CORE_UART_HPP diff --git a/src/bus/device.cpp b/src/bus/device.cpp new file mode 100644 index 0000000..85713d0 --- /dev/null +++ b/src/bus/device.cpp @@ -0,0 +1,67 @@ +#include +#include + +namespace sta +{ + Device::Device(Interface * intf) + : intf_{intf} + { + STA_ASSERT(intf != nullptr); + } + + void Device::beginTransmission() + { + intf_->acquire(); + select(); + selected_ = true; + } + + void Device::endTransmission() + { + deselect(); + selected_ = false; + intf_->release(); + } + + void Device::transfer(uint8_t value) + { + STA_ASSERT(intf_->isAcquired()); + STA_ASSERT(selected_); + + intf_->transfer(value); + } + + void Device::transfer16(uint16_t value) + { + STA_ASSERT(intf_->isAcquired()); + STA_ASSERT(selected_); + + intf_->transfer16(value); + } + + void Device::transfer(const uint8_t * buffer, size_t size) + { + STA_ASSERT(intf_->isAcquired()); + STA_ASSERT(selected_); + STA_ASSERT(buffer != nullptr); + + intf_->transfer(buffer, size); + } + + void Device::receive(uint8_t * buffer, size_t size) + { + STA_ASSERT(intf_->isAcquired()); + STA_ASSERT(selected_); + STA_ASSERT(buffer != nullptr); + + intf_->receive(buffer, size); + } + + void Device::fill(uint8_t value, size_t count) + { + STA_ASSERT(intf_->isAcquired()); + STA_ASSERT(selected_); + + intf_->fill(value, count); + } +} // namespace sta diff --git a/src/bus/i2c/device.cpp b/src/bus/i2c/device.cpp new file mode 100644 index 0000000..9d152ac --- /dev/null +++ b/src/bus/i2c/device.cpp @@ -0,0 +1,24 @@ +#include + +#include + + +namespace sta +{ + I2CDevice::I2CDevice(I2C * intf, int address, bool master, bool blocking) + : Device{intf}, intf_{intf}, address_{address}, master_{master}, blocking_{blocking} + { + STA_ASSERT(intf != nullptr); + } + + void I2CDevice::select() + { + // Initialize the interface to match the device's settings. + intf_->setSettings(address_, master_, blocking_); + } + + void I2CDevice::deselect() + { + // Nothing to do here. + } +} // namespace sta diff --git a/src/bus/i2c/i2c.cpp b/src/bus/i2c/i2c.cpp new file mode 100644 index 0000000..289bbda --- /dev/null +++ b/src/bus/i2c/i2c.cpp @@ -0,0 +1,18 @@ +#include + + +namespace sta +{ + I2C::I2C(Mutex * mutex) + : Interface{mutex} + { + + } + + void I2C::setSettings(uint16_t address, bool master, bool blocking) + { + address_ = address; + master_ = master; + blocking_ = blocking; + } +} // namespace sta diff --git a/src/bus/interface.cpp b/src/bus/interface.cpp new file mode 100644 index 0000000..8560b3b --- /dev/null +++ b/src/bus/interface.cpp @@ -0,0 +1,29 @@ +#include + +#include + +namespace sta +{ + Interface::Interface(Mutex * mutex) + : mutex_{mutex}, acquired_{false} + { + STA_ASSERT(mutex != nullptr); + } + + void Interface::acquire() + { + mutex_->acquire(); + acquired_ = true; + } + + void Interface::release() + { + mutex_->release(); + acquired_ = false; + } + + bool Interface::isAcquired() + { + return acquired_; + } +} // namespace sta diff --git a/src/bus/spi/device.cpp b/src/bus/spi/device.cpp new file mode 100644 index 0000000..60b273a --- /dev/null +++ b/src/bus/spi/device.cpp @@ -0,0 +1,38 @@ +#include + +#include + + +namespace sta +{ + SPIDevice::SPIDevice(SPI * intf, GpioPin * csPin) + : Device{intf}, intf_{intf}, csPin_{csPin} + { + STA_ASSERT(intf != nullptr); + STA_ASSERT(csPin != nullptr); + } + + void SPIDevice::transfer(const uint8_t * txBuffer, uint8_t * rxBuffer, size_t size) + { + STA_ASSERT(intf_->isAcquired()); + STA_ASSERT(txBuffer != nullptr); + STA_ASSERT(rxBuffer != nullptr); + + intf_->transfer(txBuffer, rxBuffer, size); + } + + const SPISettings & SPIDevice::settings() const + { + return intf_->settings(); + } + + void SPIDevice::select() + { + csPin_->setState(GpioPinState::GPIO_LOW); + } + + void SPIDevice::deselect() + { + csPin_->setState(GpioPinState::GPIO_HIGH); + } +} // namespace sta diff --git a/src/spi/settings.cpp b/src/bus/spi/settings.cpp similarity index 95% rename from src/spi/settings.cpp rename to src/bus/spi/settings.cpp index 7d76aa0..9fbf8e4 100644 --- a/src/spi/settings.cpp +++ b/src/bus/spi/settings.cpp @@ -1,6 +1,6 @@ -#include +#include -#include +#include #include diff --git a/src/bus/spi/spi.cpp b/src/bus/spi/spi.cpp new file mode 100644 index 0000000..012bcf3 --- /dev/null +++ b/src/bus/spi/spi.cpp @@ -0,0 +1,17 @@ +#include + +#include + +namespace sta +{ + SPI::SPI(const SPISettings & settings, Mutex * mutex /* = nullptr */) + : Interface{mutex}, settings_{settings} + { + + } + + const SPISettings & SPI::settings() + { + return settings_; + } +} // namespace sta diff --git a/src/bus/uart/settings.cpp b/src/bus/uart/settings.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/bus/uart/uart.cpp b/src/bus/uart/uart.cpp new file mode 100644 index 0000000..1b86d1e --- /dev/null +++ b/src/bus/uart/uart.cpp @@ -0,0 +1,15 @@ +#include + +namespace sta +{ + UART::UART(UARTSettings & settings, Mutex * mutex) + : Interface{mutex}, settings_{settings} + { + + } + + const UARTSettings & UART::settings() + { + return settings_; + } +} // namespace sta diff --git a/src/can/id.cpp b/src/can/id.cpp index 8ba0fd9..26c8070 100644 --- a/src/can/id.cpp +++ b/src/can/id.cpp @@ -1,4 +1,4 @@ -#include +#include namespace sta diff --git a/src/can/iter.cpp b/src/can/iter.cpp index b7a7b06..5288bef 100644 --- a/src/can/iter.cpp +++ b/src/can/iter.cpp @@ -1,6 +1,6 @@ -#include +#include -#include +#include namespace sta diff --git a/src/assert.cpp b/src/debug/assert.cpp similarity index 79% rename from src/assert.cpp rename to src/debug/assert.cpp index 5ba23b2..2f819ab 100644 --- a/src/assert.cpp +++ b/src/debug/assert.cpp @@ -1,16 +1,16 @@ -#include +#include #ifdef STA_ASSERT_ENABLED -#include +#include #include +#include namespace sta { STA_WEAK void assert_failed(const char * expr, const char * file, uint32_t line) { - // printf("%s:%d: Assertion failed: %s", file, line, expr) STA_DEBUG_PRINT(file); STA_DEBUG_PRINT(':'); STA_DEBUG_PRINT(line); diff --git a/src/printable_uart.cpp b/src/debug/printing/printable.cpp similarity index 59% rename from src/printable_uart.cpp rename to src/debug/printing/printable.cpp index 4462ac9..df6dcba 100644 --- a/src/printable_uart.cpp +++ b/src/debug/printing/printable.cpp @@ -1,131 +1,104 @@ -#include - -#include -#include +#include #include #include +#include +#include +#include - -namespace sta +namespace sta { - PrintableUART::PrintableUART(UART * intf) - : intf_{intf} - { - STA_ASSERT(intf != nullptr); - } - - - void PrintableUART::print(char c) + void Printable::print(char c) { print(&c, 1); } - void PrintableUART::print(bool b) + void Printable::print(bool b) { print(b ? "true" : "false"); } - void PrintableUART::print(double d) + void Printable::print(double d) { char buffer[64]; snprintf(buffer, sizeof(buffer), "%f", d); print(buffer); } - void PrintableUART::print(uint8_t num, IntegerBase base /* = IntegerBase::DEC */) + void Printable::print(uint8_t num, IntegerBase base) { printBase(num, base, "%" PRIu8, sizeof(num)); } - void PrintableUART::print(uint16_t num, IntegerBase base /* = IntegerBase::DEC */) + void Printable::print(uint16_t num, IntegerBase base) { printBase(num, base, "%" PRIu16, sizeof(num)); } - void PrintableUART::print(uint32_t num, IntegerBase base /* = IntegerBase::DEC */) + void Printable::print(uint32_t num, IntegerBase base) { printBase(num, base, "%" PRIu32, sizeof(num)); } - void PrintableUART::print(size_t num, IntegerBase base /* = IntegerBase::DEC */) - { - printBase(num, base, "%z", sizeof(num)); - } - - void PrintableUART::print(const char * str) + void Printable::print(const char * str) { print(str, strlen(str)); } - - void PrintableUART::print(const char * str, size_t length) - { - intf_->write(reinterpret_cast(str), length); - } - - - void PrintableUART::println() + + void Printable::println() { print("\r\n", 2); } - void PrintableUART::println(char c) + void Printable::println(char c) { print(&c, 1); println(); } - void PrintableUART::println(bool b) + void Printable::println(bool b) { print(b); println(); } - void PrintableUART::println(double d) + void Printable::println(double d) { print(d); println(); } - void PrintableUART::println(uint8_t num, IntegerBase base /* = IntegerBase::DEC */) + void Printable::println(uint8_t num, IntegerBase base) { print(num, base); println(); } - void PrintableUART::println(uint16_t num, IntegerBase base /* = IntegerBase::DEC */) + void Printable::println(uint16_t num, IntegerBase base) { print(num, base); println(); } - void PrintableUART::println(uint32_t num, IntegerBase base /* = IntegerBase::DEC */) + void Printable::println(uint32_t num, IntegerBase base) { print(num, base); println(); } - void PrintableUART::println(size_t num, IntegerBase base /* = IntegerBase::DEC */) - { - print(num, base); - println(); - } - - void PrintableUART::println(const char * str) + void Printable::println(const char * str) { println(str, strlen(str)); } - void PrintableUART::println(const char * str, size_t length) + void Printable::println(const char * str, size_t length) { print(str, length); println(); } - - - void PrintableUART::printBase(uintmax_t num, IntegerBase base, const char * fmt, size_t size) + void Printable::printBase(uintmax_t num, IntegerBase base, const char * fmt, size_t size) { switch (base) { @@ -148,14 +121,14 @@ namespace sta } } - void PrintableUART::printDec(uintmax_t num, const char * fmt) + void Printable::printDec(uintmax_t num, const char * fmt) { char buffer[64]; snprintf(buffer, sizeof(buffer), fmt, static_cast(num)); print(buffer); } - void PrintableUART::printBin(uintmax_t value, size_t digits) + void Printable::printBin(uintmax_t value, size_t digits) { // Need 8 digits for every byte char buffer[sizeof(value) * 8]; @@ -180,7 +153,7 @@ namespace sta print(buffer, digits); } - void PrintableUART::printHex(uintmax_t value, size_t digits) + void Printable::printHex(uintmax_t value, size_t digits) { // Need 2 digits for every byte char buffer[sizeof(value) * 2]; @@ -208,4 +181,5 @@ namespace sta print(buffer, digits); } -} // namespace sta + +} // namespace sta \ No newline at end of file diff --git a/src/debug/printing/printable_printf.cpp b/src/debug/printing/printable_printf.cpp new file mode 100644 index 0000000..07357f5 --- /dev/null +++ b/src/debug/printing/printable_printf.cpp @@ -0,0 +1,20 @@ +#include +#include + +#include + +namespace sta +{ + PrintablePrintf::PrintablePrintf() + { + + } + + void PrintablePrintf::print(const char * str, size_t length) + { + STA_ASSERT(str != nullptr); + STA_ASSERT(length > 0); + + printf("%.*s", length, str); + } +} // namespace sta diff --git a/src/debug/printing/printable_uart.cpp b/src/debug/printing/printable_uart.cpp new file mode 100644 index 0000000..76a63f8 --- /dev/null +++ b/src/debug/printing/printable_uart.cpp @@ -0,0 +1,25 @@ +#include + +#include +#include + +#include +#include + + +namespace sta +{ + + PrintableUART::PrintableUART(UART * intf) + : intf_{intf} + { + STA_ASSERT(intf != nullptr); + STA_ASSERT(intf->settings().mode == UARTMode::RX || intf->settings().mode == UARTMode::RX_TX); + } + + void PrintableUART::print(const char * str, size_t length) + { + intf_->transfer(reinterpret_cast(str), length); + } + +} // namespace sta diff --git a/src/debug_serial.cpp b/src/debug_serial.cpp deleted file mode 100644 index 80a0db5..0000000 --- a/src/debug_serial.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include -#ifdef STA_DEBUG_SERIAL_ENABLED - - -#ifdef STA_PLATFORM_STM32 - -#include - -#include - -// Set platform UART alias -using PlatformUART = sta::STM32UART; - -#endif // STA_PLATFORM_STM32 - - -namespace -{ - // Create platform specific serial interface - PlatformUART platformDebugSerial(&STA_DEBUG_SERIAL_UART); -} - -namespace sta -{ - // Create debug serial object using platform specific serial interface - PrintableUART DebugSerial(&platformDebugSerial); -} // namespace sta - - -#endif // STA_DEBUG_SERIAL_ENABLED diff --git a/src/devices/arduino/bus/i2c.cpp b/src/devices/arduino/bus/i2c.cpp new file mode 100644 index 0000000..c52503a --- /dev/null +++ b/src/devices/arduino/bus/i2c.cpp @@ -0,0 +1,68 @@ +#include + +#ifdef STA_PLATFORM_ARDUINO + +#include + + +namespace sta +{ + ArduinoI2C::ArduinoI2C(Mutex * mutex, uint16_t address) + : I2C{mutex} + { + Wire.begin(address); + } + + void ArduinoI2C::transfer16(uint16_t value) + { + Wire.write(value); + } + + void ArduinoI2C::transfer(const uint8_t * buffer, size_t size) + { + Wire.write(buffer, size); + } + + void ArduinoI2C::transfer(const uint8_t * txBuffer, uint8_t * rxBuffer, size_t size) + { + // NOT REALLY A THING HERE, IS IT? + } + + void ArduinoI2C::receive(uint8_t * buffer, size_t size) + { + + } + + void ArduinoI2C::fill(uint8_t value, size_t count) + { + // Initialize a buffer of size count and fill it with the value. + uint8_t *buffer = new uint8_t[count]; + memset(buffer, value, count); + + Serial.write(buffer, count); + + delete [] buffer; + } + + void ArduinoI2C::acquire() + { + I2C::acquire(); + + Wire.beginTransmission(address_); + } + + void ArduinoI2C::release() + { + Wire.endTransmission(); + + I2C::release(); + } + + ArduinoI2CDevice::ArduinoI2CDevice(I2C * intf, int address, bool master, bool blocking) + : I2CDevice{intf, address, master, blocking} + { + + } +} // namespace sta + +#endif // STA_PLATFORM_ARDUINO \ No newline at end of file diff --git a/src/devices/arduino/bus/spi.cpp b/src/devices/arduino/bus/spi.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/devices/arduino/delay.cpp b/src/devices/arduino/delay.cpp new file mode 100644 index 0000000..b3a39f1 --- /dev/null +++ b/src/devices/arduino/delay.cpp @@ -0,0 +1,20 @@ +#include + +#ifdef STA_PLATFORM_ARDUINO + +#include + +namespace sta +{ + void delayMs(uint32_t ms) + { + delay(ms); + } + + void delayUs(uint32_t us) + { + delayMicroseconds(us); + } +} // namespace sta + +#endif // STA_PLATFORM_ARDUINO \ No newline at end of file diff --git a/src/devices/arduino/gpio_pin.cpp b/src/devices/arduino/gpio_pin.cpp new file mode 100644 index 0000000..1d3b232 --- /dev/null +++ b/src/devices/arduino/gpio_pin.cpp @@ -0,0 +1,28 @@ +#include + +#ifdef STA_PLATFORM_ARDUINO + +#include + +namespace sta +{ + ArduinoGpioPin::ArduinoGpioPin(uint16_t pin) : pin_{pin} { } + + void ArduinoGpioPin::setState(GpioPinState state) + { + digitalWrite(pin_, (state == GpioPinState::GPIO_LOW) ? LOW : HIGH); + } + + GpioPinState ArduinoGpioPin::getState() + { + return digitalRead(pin_) == HIGH ? GpioPinState::GPIO_HIGH : GpioPinState::GPIO_LOW; + } + + uint16_t ArduinoGpioPin::getPin() const + { + return pin_; + } + +} // namespace sta + +#endif // STA_PLATFORM_ARDUINO \ No newline at end of file diff --git a/src/devices/raspi/bus/i2c.cpp b/src/devices/raspi/bus/i2c.cpp new file mode 100644 index 0000000..35850a3 --- /dev/null +++ b/src/devices/raspi/bus/i2c.cpp @@ -0,0 +1,140 @@ +#include + +#ifdef STA_PLATFORM_RASPI + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + + +namespace sta +{ + RaspiI2C::RaspiI2C(I2CNode node, Mutex * mutex, bool persistent_open) + : I2C{mutex}, persistent_open_{persistent_open} + { + // Safer version of malloc + strcpy + i2cdev_ = strdup(node == I2CNode::DEV_1 ? "/dev/i2c-1" : "/dev/i2c-2"); + + STA_ASSERT(i2cdev_ != nullptr); + } + + RaspiI2C::~RaspiI2C() + { + if (i2cdev_ != NULL ) { + free(i2cdev_); + i2cdev_ = NULL; + } + + if (open_) { + close(i2cfd_); + } + } + + void RaspiI2C::transfer(uint8_t value) + { + STA_ASSERT(open_); + + selectAddress(); + ssize_t n_out = write(i2cfd_, &value, 1); + + STA_ASSERT(n_out == 1); + } + + void RaspiI2C::transfer16(uint16_t value) + { + STA_ASSERT(open_); + + selectAddress(); + ssize_t n_out = write(i2cfd_, &value, 2); + + STA_ASSERT(n_out == 2); + } + + void RaspiI2C::transfer(const uint8_t * buffer, size_t size) + { + STA_ASSERT(open_); + + selectAddress(); + ssize_t n_out = write(i2cfd_, buffer, size); + + STA_ASSERT(n_out == size); + } + + void RaspiI2C::receive(uint8_t * buffer, size_t size) + { + STA_ASSERT(open_); + + selectAddress(); + ssize_t n_in = read(i2cfd_, buffer, size); + + STA_ASSERT(n_in >= 0); + } + + void RaspiI2C::fill(uint8_t value, size_t count) + { + STA_ASSERT(open_); + + selectAddress(); + + // Initialize a buffer of size count and fill it with the value. + uint8_t *buffer = new uint8_t[count]; + memset(buffer, value, count); + + ssize_t n_out = write(i2cfd_, buffer, count); + + STA_ASSERT(n_out == count); + + delete [] buffer; + } + + void RaspiI2C::selectAddress() + { + // Select the slave with the given address. + int rslt = ioctl(i2cfd_, I2C_SLAVE, address_); + + STA_ASSERT(rslt != -1); + } + + void RaspiI2C::acquire() + { + I2C::acquire(); + + if (open_) { + return; + } + + i2cfd_ = open(i2cdev_, O_RDWR); + open_ = true; + + STA_ASSERT(i2cfd_ >= 0); + } + + void RaspiI2C::release() + { + if (!persistent_open_ && open_) { + close(i2cfd_); + open_ = false; + } + + I2C::release(); + } + + RaspiI2CDevice::RaspiI2CDevice(RaspiI2C * intf, uint16_t address_10bit, bool master, bool blocking) + : I2CDevice { intf, address_10bit, master, blocking } + { + + } + + +} // namespace sta + +#endif // STA_PLATFORM_RASPI diff --git a/src/devices/raspi/bus/spi.cpp b/src/devices/raspi/bus/spi.cpp new file mode 100644 index 0000000..b7eb57b --- /dev/null +++ b/src/devices/raspi/bus/spi.cpp @@ -0,0 +1,314 @@ +#include + +#ifdef STA_PLATFORM_RASPI + +#include +#include +#include +#include +#include + +#include +#include +#include + +// Imports needed for SPI handling on Linux. +#include +#include +#include +#include +#include + +#define STA_DEBUG_IOCTL_WRITE(result) STA_ASSERT_MSG(result >= 0, "ioctl writing failed!") +#define STA_DEBUG_IOCTL_READ(result) STA_ASSERT_MSG(result >= 0, "ioctl reading failed!") +#define STA_DEBUG_IOCTL_SEND(result) STA_ASSERT_MSG(result >= 0, "ioctl sending spi message failed!") + +#define STA_DEBUG_FD_OPEN() STA_ASSERT_MSG(open_, "File descriptor wasn't opened!") +#define STA_DEBUG_NULLPTR(ptr) STA_ASSERT_MSG(ptr != nullptr, "Pointer is nullptr!") + + +namespace sta +{ + + RaspiSPI::RaspiSPI(SPINode node, const SPISettings & settings, Mutex * mutex, bool persistent_open) + : SPI(settings, mutex), open_{ false }, persistent_open_{ persistent_open }, settings_{ settings } + { + // Check validity of parameters. + STA_DEBUG_NULLPTR(mutex); + + open_ = false; + + // Safer version of malloc + strcpy + spidev_ = strdup(node == SPINode::DEV_0_0 ? "/dev/spidev0.0" : "/dev/spidev0.1"); + + // Check if memory allocation was successful. + STA_DEBUG_NULLPTR(spidev_); + } + + RaspiSPI::~RaspiSPI() + { + if (spidev_ != NULL ) { + free(spidev_); + spidev_ = NULL; + } + + if (open_) { + close(spifd_); + } + } + + void RaspiSPI::transfer(uint8_t value) + { + STA_DEBUG_FD_OPEN(); + + struct spi_ioc_transfer spi_message[1]; + + // According to the documentation, spi_message should be zero intialized. + memset(spi_message, 0, sizeof(spi_message)); + spi_message[0].tx_buf = (unsigned long)&value; + spi_message[0].len = 1; + + // For some reasons, this line makes the SPI interface work for the BMP388. + spi_message[0].cs_change = 1; + + int result = ioctl(spifd_, SPI_IOC_MESSAGE(1), spi_message); + + if (result < 0) { + printf("Sending failed with error '%s'! \n", strerror(errno)); + } + + STA_DEBUG_IOCTL_SEND(result); + } + + void RaspiSPI::transfer16(uint16_t value) + { + STA_DEBUG_FD_OPEN(); + + struct spi_ioc_transfer spi_message[1]; + + // According to the documentation, spi_message should be zero intialized. + memset(spi_message, 0, sizeof(spi_message)); + spi_message[0].tx_buf = (unsigned long)&value; + spi_message[0].len = 1; + spi_message[0].cs_change = 1; + + int result = ioctl(spifd_, SPI_IOC_MESSAGE(1), spi_message); + + if (result < 0) { + printf("Sending failed with error '%s'! \n", strerror(errno)); + } + + STA_DEBUG_IOCTL_SEND(result); + } + + void RaspiSPI::transfer(const uint8_t * buffer, size_t size) + { + STA_DEBUG_FD_OPEN(); + STA_DEBUG_NULLPTR(buffer); + STA_ASSERT_MSG(size != 0, "Buffer size cannot be 0!"); + + struct spi_ioc_transfer spi_message[1]; + + // According to the documentation, spi_message should be zero intialized. + memset(spi_message, 0, sizeof(spi_message)); + spi_message[0].tx_buf = (unsigned long)buffer; + spi_message[0].len = size; + + int result = ioctl(spifd_, SPI_IOC_MESSAGE(1), spi_message); + + if (result < 0) { + printf("Sending failed with error '%s'! \n", strerror(errno)); + } + + STA_DEBUG_IOCTL_SEND(result); + } + + void RaspiSPI::transfer(const uint8_t * txBuffer, uint8_t * rxBuffer, size_t size) + { + STA_DEBUG_FD_OPEN(); + STA_DEBUG_NULLPTR(txBuffer); + STA_DEBUG_NULLPTR(rxBuffer); + STA_ASSERT_MSG(size != 0, "Buffer size cannot be 0!"); + + struct spi_ioc_transfer spi_message[1]; + + // According to the documentation, spi_message should be zero intialized. + memset(spi_message, 0, sizeof(spi_message)); + + spi_message[0].rx_buf = (unsigned long)rxBuffer; + spi_message[0].tx_buf = (unsigned long)txBuffer; + spi_message[0].len = size; + + int result = ioctl(spifd_, SPI_IOC_MESSAGE(1), spi_message); + + if (result < 0) { + printf("Sending failed with error '%s'! \n", strerror(errno)); + } + + STA_DEBUG_IOCTL_SEND(result); + } + + void RaspiSPI::receive(uint8_t * buffer, size_t size) + { + STA_DEBUG_FD_OPEN(); + STA_DEBUG_NULLPTR(buffer); + STA_ASSERT_MSG(size != 0, "Buffer size cannot be 0!"); + + struct spi_ioc_transfer spi_message[1]; + + // According to the documentation, spi_message should be zero intialized. + memset(spi_message, 0, sizeof(spi_message)); + + spi_message[0].rx_buf = (unsigned long)buffer; + spi_message[0].len = size; + + int result = ioctl(spifd_, SPI_IOC_MESSAGE(1), spi_message); + + STA_DEBUG_IOCTL_SEND(result); + } + + void RaspiSPI::fill(uint8_t value, size_t count) + { + STA_DEBUG_FD_OPEN(); + STA_ASSERT_MSG(count != 0, "Buffer size cannot be 0!"); + + uint8_t * buffer = new uint8_t[count]; + memset(buffer, value, count); + + struct spi_ioc_transfer spi_message[1]; + memset(spi_message, 0, sizeof(spi_message)); + spi_message[0].tx_buf = (unsigned long)buffer; + spi_message[0].len = count; + + int result = ioctl(spifd_, SPI_IOC_MESSAGE(1), spi_message); + + STA_DEBUG_IOCTL_SEND(result); + + delete[] buffer; + } + + void RaspiSPI::update_setting(int setting, int value) + { + + } + + void RaspiSPI::get_setting(int setting, void * rslt_ptr) + { + STA_DEBUG_FD_OPEN(); + int result = ioctl(spifd_, setting, rslt_ptr); + STA_DEBUG_IOCTL_READ(result); + } + + void RaspiSPI::update_settings() + { + STA_DEBUG_FD_OPEN(); + + switch (settings_.mode) + { + case SPIMode::MODE_0: + mode_ = SPI_MODE_0; + break; + case SPIMode::MODE_1: + mode_ = SPI_MODE_1; + break; + case SPIMode::MODE_2: + mode_ = SPI_MODE_2; + break; + case SPIMode::MODE_3: + mode_ = SPI_MODE_3; + break; + default: + STA_ASSERT_MSG(false, "Case for SPIMode enum not handled"); + STA_UNREACHABLE(); + } + + dataSize_ = settings_.dataSize == SPIDataSize::SIZE_8 ? 0 : 16; + bitOrder_ = settings_.bitOrder == SPIBitOrder::MSB ? 0 : 1; + clkSpeed_ = settings_.clkSpeed; + + // Set the spi mode. + int result = ioctl(spifd_, SPI_IOC_WR_MODE, &mode_); + STA_DEBUG_IOCTL_WRITE(result); + + if (result < 0) { + printf("Update mode failed with error '%s'! \n", strerror(errno)); + } + + // Set the word size. According to the documentation "the value zero signifies eight bits". + result = ioctl(spifd_, SPI_IOC_WR_BITS_PER_WORD, &dataSize_); + STA_DEBUG_IOCTL_WRITE(result); + + if (result < 0) { + printf("Update dataSize failed with error '%s'! \n", strerror(errno)); + } + + // Set the bit order. According to the documentation zero means MSB first, everything else means LSB first. + result = ioctl(spifd_, SPI_IOC_WR_LSB_FIRST, &bitOrder_); + STA_DEBUG_IOCTL_WRITE(result); + + if (result < 0) { + printf("Update endianness failed with error '%s'! \n", strerror(errno)); + } + + // Set the maximum clock speed. + result = ioctl(spifd_, SPI_IOC_WR_MAX_SPEED_HZ, &clkSpeed_); + STA_DEBUG_IOCTL_WRITE(result); + + if (result < 0) { + printf("Update clock speed failed with error '%s'! \n", strerror(errno)); + } + + #if defined(DEBUG) + uint8_t r_mode = 0; + get_setting(SPI_IOC_RD_MODE, &r_mode); + STA_ASSERT_MSG(r_mode == mode_, "The mode wasn't set correctly!"); + + uint8_t r_dataSize = 0; + get_setting(SPI_IOC_WR_BITS_PER_WORD, &r_dataSize); + STA_ASSERT_MSG(r_dataSize == (settings_.dataSize == SPIDataSize::SIZE_8 ? 8 : 16), "The data size wasn't set correctly!"); + + uint8_t r_bitOrder = 0; + get_setting(SPI_IOC_RD_LSB_FIRST, &r_bitOrder); + STA_ASSERT_MSG(r_bitOrder == (settings_.bitOrder == SPIBitOrder::MSB ? 0 : 1), "The data size wasn't set correctly!"); + + uint32_t r_clk_Speed; + get_setting(SPI_IOC_RD_MAX_SPEED_HZ, &r_clk_Speed); + STA_ASSERT_MSG(r_clk_Speed == settings_.clkSpeed, "The clock speed wasn't set correctly!"); + #endif // STA_DEBUG + } + + void RaspiSPI::acquire() + { + SPI::acquire(); + + STA_ASSERT(spidev_ != nullptr); + + /* open spidev device */ + if (open_ == true) + return; + + spifd_ = open(spidev_, O_RDWR); + open_ = true; + + STA_ASSERT(spifd_ >= 0); + + update_settings(); + } + + void RaspiSPI::release() + { + if (!persistent_open_ && open_) { + close(spifd_); + } + + SPI::release(); + } + + RaspiSPIDevice::RaspiSPIDevice(RaspiSPI * intf) : SPIDevice { intf, RaspiGpioPin::DUMMY_GPIO } + { + + } +} // namespace sta + + +#endif // STA_PlATFORM_RASPI diff --git a/src/devices/raspi/delay.cpp b/src/devices/raspi/delay.cpp new file mode 100644 index 0000000..3eb9641 --- /dev/null +++ b/src/devices/raspi/delay.cpp @@ -0,0 +1,23 @@ +#include +#ifdef STA_PLATFORM_RASPI + +#include + +#include +#include + + +namespace sta +{ + void delayMs(uint32_t ms) + { + delay(ms); + } + + void delayUs(uint32_t us) + { + delayMicroseconds(us); + } +} // namespace sta + +#endif // STA_PLATFORM_RASPI diff --git a/src/devices/raspi/gpio_pin.cpp b/src/devices/raspi/gpio_pin.cpp new file mode 100644 index 0000000..e845997 --- /dev/null +++ b/src/devices/raspi/gpio_pin.cpp @@ -0,0 +1,43 @@ +#include +#ifdef STA_RASPI_GPIO_ENABLED + +#include +#include + +namespace sta +{ + RaspiGpioPin::RaspiGpioPin(uint8_t pin, GpioMode mode) : pin_{ pin }, mode_{ mode } + { + pinMode(pin, mode == GpioMode::GPIO_INPUT ? INPUT : OUTPUT); + } + + void RaspiGpioPin::setState(GpioPinState state) + { + digitalWrite(pin_, state == GpioPinState::GPIO_LOW ? LOW : HIGH); + } + + GpioPinState RaspiGpioPin::getState() + { + return digitalRead(pin_) == LOW ? GpioPinState::GPIO_LOW : GpioPinState::GPIO_HIGH; + } + + class DummyGpioPin : public RaspiGpioPin + { + public: + DummyGpioPin() : RaspiGpioPin { 0, GpioMode::GPIO_INPUT } {} + + void setState(GpioPinState state) override {} + + GpioPinState getState() override { + // This should really never be called since the code might rely on the returned value to be accurate. + STA_UNREACHABLE(); + } + }; + + static DummyGpioPin dummyGpio; + + RaspiGpioPin * RaspiGpioPin::DUMMY_GPIO = &dummyGpio; +} // namespace sta + + +#endif // STA_ARDUINO_GPIO_ENABLED diff --git a/src/devices/stm32/adc.cpp b/src/devices/stm32/adc.cpp new file mode 100644 index 0000000..5c5d663 --- /dev/null +++ b/src/devices/stm32/adc.cpp @@ -0,0 +1,33 @@ +#include + +#ifdef STA_STM32_ADC_ENABLED + +#include + +namespace sta +{ + STM32ADC::STM32ADC(ADC_HandleTypeDef * handle) + : handle_{handle} + { + STA_ASSERT(handle != nullptr); + } + + void STM32ADC::start() + { + HAL_ADC_Start(handle_); + } + + void STM32ADC::poll(uint32_t timeout) + { + HAL_StatusTypeDef res = HAL_ADC_PollForConversion(handle_, timeout); + + STA_ASSERT(res == HAL_OK); + } + + uint32_t STM32ADC::getValue() + { + return HAL_ADC_GetValue(handle_); + } +} // namespace sta + +#endif // STA_STM32_ADC_ENABLED diff --git a/src/devices/stm32/bus/i2c.cpp b/src/devices/stm32/bus/i2c.cpp new file mode 100644 index 0000000..6478f8a --- /dev/null +++ b/src/devices/stm32/bus/i2c.cpp @@ -0,0 +1,127 @@ +#include + +#include +#include + +#ifdef STA_STM32_I2C_ENABLED + +namespace sta +{ + STM32I2C::STM32I2C(I2C_HandleTypeDef * handle, Mutex * mutex) + : I2C{mutex}, handle_{handle} + { + STA_ASSERT(handle != nullptr); + } + + void STM32I2C::transfer(uint8_t value) + { + HAL_StatusTypeDef res; + + if (master_) + { + res = HAL_I2C_Master_Transmit(handle_, address_, &value, 1, timeout_); + } else { + res = HAL_I2C_Slave_Transmit(handle_, &value, 1, timeout_); + } + + STA_ASSERT(res == HAL_OK); + } + + void STM32I2C::transfer16(uint16_t value) + { + HAL_StatusTypeDef res; + + if (blocking_) + { + if (master_) + { + res = HAL_I2C_Master_Transmit(handle_, address_, reinterpret_cast(&value), 2, timeout_); + } else { + res = HAL_I2C_Slave_Transmit(handle_, reinterpret_cast(&value), 2, timeout_); + } + } else { + if (master_) + { + res = HAL_I2C_Slave_Transmit_IT(handle_, reinterpret_cast(&value), 2); + } else { + res = HAL_I2C_Slave_Transmit_IT(handle_, reinterpret_cast(&value), 2); + } + } + + STA_ASSERT(res == HAL_OK); + } + + void STM32I2C::transfer(const uint8_t * buffer, size_t size) + { + HAL_StatusTypeDef res; + + /* + * It's undecided if we want to change the parameter for this function. Since the transmission + * doesn't take a const buffer as an argument, we are using this fix by creating a temporary buffer. + */ + uint8_t * temp_buffer = new uint8_t[size]; + memcpy(temp_buffer, buffer, size); + + if (blocking_) + { + if (master_) + { + res = HAL_I2C_Master_Transmit(handle_, address_, temp_buffer, size, timeout_); + } else { + res = HAL_I2C_Slave_Transmit(handle_, temp_buffer, size, timeout_); + } + } else { + if (master_) { + res = HAL_I2C_Master_Transmit_IT(handle_, address_, temp_buffer, size); + } else { + res = HAL_I2C_Slave_Transmit_IT(handle_, temp_buffer, size); + } + } + + delete [] temp_buffer; + + STA_ASSERT(res == HAL_OK); + } + + void STM32I2C::receive(uint8_t * buffer, size_t size) + { + HAL_StatusTypeDef res; + + if (blocking_) { + if (master_) { + res = HAL_I2C_Master_Receive(handle_, address_, buffer, size, timeout_); + } else { + res = HAL_I2C_Slave_Receive(handle_, buffer, size, timeout_); + } + } else { + if (master_) { + res = HAL_I2C_Master_Receive_IT(handle_, address_, buffer, size); + } else { + res = HAL_I2C_Slave_Receive_IT(handle_, buffer, size); + } + } + + STA_ASSERT(res == HAL_OK); + } + + void STM32I2C::fill(uint8_t value, size_t count) + { + // Initialize a buffer of size count and fill it with the value. + uint8_t *buffer = new uint8_t[count]; + memset(buffer, value, count); + + // Transfer the buffer via the bus. + transfer(buffer, count); + + delete [] buffer; + } + + STM32I2CDevice::STM32I2CDevice(STM32I2C * intf, int address, bool master, bool blocking) + : I2CDevice(intf, address, master, blocking) + { + + } + +} // namespace sta + +#endif // STA_STM32_I2C_ENABLED diff --git a/src/stm32/spi.cpp b/src/devices/stm32/bus/spi.cpp similarity index 97% rename from src/stm32/spi.cpp rename to src/devices/stm32/bus/spi.cpp index ec5af2a..becfaac 100644 --- a/src/stm32/spi.cpp +++ b/src/devices/stm32/bus/spi.cpp @@ -1,7 +1,7 @@ -#include +#include #ifdef STA_STM32_SPI_ENABLED -#include +#include #include #include @@ -66,7 +66,7 @@ namespace sta } - STM32SPI::STM32SPI(SPI_HandleTypeDef * handle, uint32_t pclkFreq, Mutex * mutex = nullptr) + STM32SPI::STM32SPI(SPI_HandleTypeDef * handle, uint32_t pclkFreq, Mutex * mutex) : SPI(getSPISettings(handle, pclkFreq), mutex), handle_{handle} { STA_ASSERT(handle != nullptr); @@ -157,10 +157,8 @@ namespace sta } } - - - STM32SPIDevice::STM32SPIDevice(STM32SPI * intf, STM32GpioPin csPin) - : SPIDevice(intf, &csPin_), csPin_{csPin} + STM32SPIDevice::STM32SPIDevice(STM32SPI * intf, STM32GpioPin * csPin) + : SPIDevice(intf, csPin) {} } // namespace sta diff --git a/src/devices/stm32/bus/uart.cpp b/src/devices/stm32/bus/uart.cpp new file mode 100644 index 0000000..300f49f --- /dev/null +++ b/src/devices/stm32/bus/uart.cpp @@ -0,0 +1,53 @@ +#include +#ifdef STA_STM32_UART_ENABLED + +#include +#include + +namespace sta +{ + STM32UART::STM32UART(UART_HandleTypeDef * handle, UARTSettings & settings, Mutex * mutex) + : UART{settings, mutex}, handle_{handle} + { + STA_ASSERT(handle != nullptr); + } + + void STM32UART::transfer(uint8_t value) + { + HAL_UART_Transmit(handle_, &value, 1, HAL_MAX_DELAY); + } + + void STM32UART::transfer16(uint16_t value) + { + HAL_UART_Transmit(handle_, reinterpret_cast(&value), 2, HAL_MAX_DELAY); + } + + void STM32UART::transfer(const uint8_t * buffer, size_t size) + { + STA_ASSERT(buffer != nullptr); + + HAL_UART_Transmit(handle_, const_cast(buffer), size, HAL_MAX_DELAY); + } + + void STM32UART::receive(uint8_t * buffer, size_t size) + { + STA_ASSERT(buffer != nullptr); + + HAL_UART_Receive(handle_, buffer, size, HAL_MAX_DELAY); + } + + void STM32UART::fill(uint8_t value, size_t count) + { + // Initialize a buffer of size count and fill it with the value. + uint8_t *buffer = new uint8_t[count]; + memset(buffer, value, count); + + // Transfer the buffer via the bus. + transfer(buffer, count); + + delete [] buffer; + } +} // namespace sta + + +#endif // STA_STM32_UART_ENABLED diff --git a/src/stm32/can.cpp b/src/devices/stm32/can.cpp similarity index 98% rename from src/stm32/can.cpp rename to src/devices/stm32/can.cpp index 5c39fc7..0c485ea 100644 --- a/src/stm32/can.cpp +++ b/src/devices/stm32/can.cpp @@ -1,7 +1,7 @@ -#include +#include #ifdef STA_STM32_CAN_ENABLED -#include +#include #include diff --git a/src/devices/stm32/delay.cpp b/src/devices/stm32/delay.cpp new file mode 100644 index 0000000..8f51d73 --- /dev/null +++ b/src/devices/stm32/delay.cpp @@ -0,0 +1,79 @@ +#include + +#ifdef STA_PLATFORM_STM32 + +#include +#include + +#include +#include + + +namespace sta +{ + void delayMs(uint32_t ms) + { + HAL_Delay(ms); + } +} // namespace sta + + +#ifdef STA_STM32_DELAY_US_TIM + +#ifndef HAL_TIM_MODULE_ENABLED +# error "STM32 HAL TIM module not enabled!" +#endif // HAL_TIM_MODULE_ENABLED + +#include + +namespace sta +{ + uint32_t gDelayUsMul = 1; + + bool isValidDelayUsTIM() + { + // Get PCLK multiplier for TIM clock + uint32_t pclkMul = 1; + switch (STA_STM32_DELAY_US_TIM.Init.ClockDivision) + { + case TIM_CLOCKDIVISION_DIV1: + pclkMul = 1; + break; + case TIM_CLOCKDIVISION_DIV2: + pclkMul = 2; + break; + case TIM_CLOCKDIVISION_DIV4: + pclkMul = 4; + break; + default: + STA_ASSERT(false); + STA_UNREACHABLE(); + } + + // Calculate TIM clock frequency + uint32_t clkFreq = pclkMul * STA_STM32_GET_HANDLE_PCLK_FREQ_FN(STA_STM32_DELAY_US_TIM)(); + // Calculate update frequency based on prescaler value + uint32_t prescaler = (STA_STM32_DELAY_US_TIM.Init.Prescaler) ? STA_STM32_DELAY_US_TIM.Init.Prescaler : 1; + uint32_t updateFreq = clkFreq / prescaler; + + gDelayUsMul = updateFreq / 1000000; + + // TIM must have at least microsecond precision (>= 1 MHz frequency) + return (updateFreq >= 1000000); + } + + void delayUs(uint32_t us) + { + // Check if the specified timer is usable for microsecond delays. + STA_ASSERT(isValidDelayUsTIM()); + + __HAL_TIM_SET_COUNTER(&STA_STM32_DELAY_US_TIM, 0); + while (__HAL_TIM_GET_COUNTER(&STA_STM32_DELAY_US_TIM) < us * gDelayUsMul); + } + +} // namespace sta + +#endif // STA_STM32_DELAY_US_TIM + + +#endif // STA_PLATFORM_STM32 diff --git a/src/stm32/gpio_pin.cpp b/src/devices/stm32/gpio_pin.cpp similarity index 84% rename from src/stm32/gpio_pin.cpp rename to src/devices/stm32/gpio_pin.cpp index c0d6a67..416d3ab 100644 --- a/src/stm32/gpio_pin.cpp +++ b/src/devices/stm32/gpio_pin.cpp @@ -1,7 +1,7 @@ -#include +#include #ifdef STA_STM32_GPIO_ENABLED -#include +#include #include @@ -15,7 +15,12 @@ namespace sta void STM32GpioPin::setState(GpioPinState state) { - HAL_GPIO_WritePin(port_, pin_, (state == GpioPinState::LOW) ? GPIO_PIN_RESET : GPIO_PIN_SET); + HAL_GPIO_WritePin(port_, pin_, (state == GpioPinState::GPIO_LOW) ? GPIO_PIN_RESET : GPIO_PIN_SET); + } + + GpioPinState STM32GpioPin::getState() + { + return HAL_GPIO_ReadPin(port_, pin_) == GPIO_PIN_RESET ? GpioPinState::GPIO_LOW : GpioPinState::GPIO_HIGH; } GPIO_TypeDef * STM32GpioPin::getPort() const diff --git a/src/stm32/init.cpp b/src/devices/stm32/init.cpp similarity index 88% rename from src/stm32/init.cpp rename to src/devices/stm32/init.cpp index fed0f3c..0f06016 100644 --- a/src/stm32/init.cpp +++ b/src/devices/stm32/init.cpp @@ -1,6 +1,6 @@ -#include +#include -#include +#include #ifdef STA_STM32_DELAY_US_TIM diff --git a/src/devices/template/custom_printable.cpp b/src/devices/template/custom_printable.cpp new file mode 100644 index 0000000..590859a --- /dev/null +++ b/src/devices/template/custom_printable.cpp @@ -0,0 +1,18 @@ +#include + +#ifdef STA_PLATFORM_YOUR_DEVICE + +#include + +namespace sta +{ + void CustomPrintable::print(const char * str, size_t length) + { + STA_ASSERT(str != nullptr); + STA_ASSERT(length > 0); + + // YOUR CODE HERE + } +} // namespace sta + +#endif // STA_PLATFORM_YOUR_DEVICE diff --git a/src/devices/template/delay.cpp b/src/devices/template/delay.cpp new file mode 100644 index 0000000..3b19826 --- /dev/null +++ b/src/devices/template/delay.cpp @@ -0,0 +1,34 @@ +/** + * @file delay.cpp + * @author (@.com) + * @brief + * @version 0.1 + * @date 2023-06-13 + * + * @copyright Copyright (c) 2023 + * + * How to modify this file: + * - Ctrl + F and replace "YOUR_DEVICE" with the appropriate name. + * - Implement the functions delayMs and delayUs. + * - Remove the import if no longer needed. + */ + +#include +#ifdef STA_PLATFORM_YOUR_DEVICE + +#include + +namespace sta +{ + void delayMs(uint32_t ms) + { + STA_NOT_IMPLEMENTED(); + } + + void delayUs(uint32_t us) + { + STA_NOT_IMPLEMENTED(); + } +} // namespace sta + +#endif // STA_PLATFORM_YOUR_DEVICE diff --git a/src/i2c.cpp b/src/i2c.cpp deleted file mode 100644 index 0f32c26..0000000 --- a/src/i2c.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include - -namespace sta { - I2cDevice::I2cDevice(uint16_t address_7bit, Mutex* mutex, bool master, bool blocking) { - this->address = address_7bit << 1; - this->mutex = mutex; - this->master = master; - this->blocking = blocking; - } - - void I2cDevice::acquire() { - if (this->mutex != nullptr) { - mutex->acquire(); - } - } - - void I2cDevice::release() { - if (this->mutex != nullptr) { - mutex->release(); - } - } -} diff --git a/src/spi/device.cpp b/src/spi/device.cpp deleted file mode 100644 index cced053..0000000 --- a/src/spi/device.cpp +++ /dev/null @@ -1,88 +0,0 @@ -#include - -#include - - -namespace sta -{ - SPIDevice::SPIDevice(SPI * intf, GpioPin * csPin) - : intf_{intf}, csPin_{csPin} - { - STA_ASSERT(intf != nullptr); - STA_ASSERT(csPin != nullptr); - } - - void SPIDevice::beginTransmission() - { - // Acquire SPI access and activate device - intf_->acquire(); - select(); - } - - void SPIDevice::endTransmission() - { - // Deactivate device and release SPI access - deselect(); - intf_->release(); - } - - - // Forward I/O operations to SPI interface - - void SPIDevice::transfer(uint8_t data) - { - intf_->transfer(data); - } - - void SPIDevice::transfer16(uint16_t data) - { - intf_->transfer16(data); - } - - void SPIDevice::transfer(const uint8_t * buffer, size_t size) - { - STA_ASSERT(buffer != nullptr); - - intf_->transfer(buffer, size); - } - - void SPIDevice::transfer(const uint8_t * txBuffer, uint8_t * rxBuffer, size_t size) - { - STA_ASSERT(txBuffer != nullptr); - STA_ASSERT(rxBuffer != nullptr); - STA_ASSERT(size != 0); - - intf_->transfer(txBuffer, rxBuffer, size); - } - - void SPIDevice::receive(uint8_t * buffer, size_t size) - { - STA_ASSERT(buffer != nullptr); - - intf_->receive(buffer, size); - } - - void SPIDevice::fill(uint8_t value, size_t count) - { - STA_ASSERT(count != 0); - - intf_->fill(value, count); - } - - - const SpiSettings & SPIDevice::settings() const - { - return intf_->settings(); - } - - - void SPIDevice::select() - { - csPin_->setState(GpioPinState::LOW); - } - - void SPIDevice::deselect() - { - csPin_->setState(GpioPinState::HIGH); - } -} // namespace sta diff --git a/src/spi/spi.cpp b/src/spi/spi.cpp deleted file mode 100644 index 56d38db..0000000 --- a/src/spi/spi.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include - - -namespace sta -{ - SPI::SPI(const SPISettings & settings, Mutex * mutex /* = nullptr */) - : settings_{settings}, mutex_{mutex} - {} - - const SPISettings & SPI::settings() const - { - return settings_; - } - - void SPI::acquire() - { - if (mutex_ != nullptr) - mutex_->acquire(); - } - - void SPI::release() - { - if (mutex_ != nullptr) - mutex_->release(); - } -} // namespace sta diff --git a/src/stm32/delay.cpp b/src/stm32/delay.cpp deleted file mode 100644 index a3b9a98..0000000 --- a/src/stm32/delay.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include -#ifdef STA_PLATFORM_STM32 - -#include -#include - -#include -#include - - -namespace sta -{ - void delayMs(uint32_t ms) - { - HAL_Delay(ms); - } -} // namespace sta - - -#ifdef STA_STM32_DELAY_US_TIM - -#ifndef HAL_TIM_MODULE_ENABLED -# error "STM32 HAL TIM module not enabled!" -#endif // HAL_TIM_MODULE_ENABLED - -#include - -namespace sta -{ - uint32_t gDelayUsMul = 1; - - void delayUs(uint32_t us) - { - __HAL_TIM_SET_COUNTER(&STA_STM32_DELAY_US_TIM, 0); - while (__HAL_TIM_GET_COUNTER(&STA_STM32_DELAY_US_TIM) < us * gDelayUsMul); - } - - - bool isValidDelayUsTIM() - { - // Get PCLK multiplier for TIM clock - uint32_t pclkMul = 1; - switch (STA_STM32_DELAY_US_TIM.Init.ClockDivision) - { - case TIM_CLOCKDIVISION_DIV1: - pclkMul = 1; - break; - case TIM_CLOCKDIVISION_DIV2: - pclkMul = 2; - break; - case TIM_CLOCKDIVISION_DIV4: - pclkMul = 4; - break; - default: - STA_ASSERT(false); - STA_UNREACHABLE(); - } - - // Calculate TIM clock frequency - uint32_t clkFreq = pclkMul * STA_STM32_GET_HANDLE_PCLK_FREQ_FN(STA_STM32_DELAY_US_TIM)(); - // Calculate update frequency based on prescaler value - uint32_t prescaler = (STA_STM32_DELAY_US_TIM.Init.Prescaler) ? STA_STM32_DELAY_US_TIM.Init.Prescaler : 1; - uint32_t updateFreq = clkFreq / prescaler; - - gDelayUsMul = updateFreq / 1000000; - - // TIM must have at least microsecond precision (>= 1 MHz frequency) - return (updateFreq >= 1000000); - } -} // namespace sta - -#endif // STA_STM32_DELAY_US_TIM - - -#endif // STA_PLATFORM_STM32 diff --git a/src/stm32/i2c.cpp b/src/stm32/i2c.cpp deleted file mode 100644 index 289bfc1..0000000 --- a/src/stm32/i2c.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include - -namespace sta { - STM32I2cDevice::STM32I2cDevice(I2C_HandleTypeDef* i2cHandle, uint16_t address, Mutex* mutex, bool master, bool blocking) - : I2cDevice(address, mutex, master, blocking) { - this->master = master; - } - - bool STM32I2cDevice::transmit(uint8_t* data, uint16_t size) { - HAL_StatusTypeDef res; - - if (this->blocking) { - if (!this->master) { - res = HAL_I2C_Master_Transmit(i2cHandle, address, data, size, this->timeout); - } else { - res = HAL_I2C_Slave_Transmit(i2cHandle , data, size, this->timeout); - } - } else { - if (!this->master) { - res = HAL_I2C_Master_Transmit_IT(i2cHandle, address, data, size); - } else { - res = HAL_I2C_Slave_Transmit_IT(i2cHandle , data, size); - } - } - - return res == HAL_OK; - } - - bool STM32I2cDevice::receive(uint8_t* data, uint16_t size) { - HAL_StatusTypeDef res; - - if (this->blocking) { - if (!this->master) { - res = HAL_I2C_Master_Receive(i2cHandle, address, data, size, this->timeout); - } else { - res = HAL_I2C_Slave_Receive(i2cHandle , data, size, this->timeout); - } - } else { - if (!this->master) { - res = HAL_I2C_Master_Receive_IT(i2cHandle, address, data, size); - } else { - res = HAL_I2C_Slave_Receive_IT(i2cHandle , data, size); - } - } - - return res == HAL_OK; - } - - bool STM32I2cDevice::deviceReady() { - HAL_StatusTypeDef res = HAL_I2C_IsDeviceReady(this->i2cHandle, this->address, 8, this->timeout); - return res == HAL_OK; - } -} diff --git a/src/stm32/uart.cpp b/src/stm32/uart.cpp deleted file mode 100644 index 094b34e..0000000 --- a/src/stm32/uart.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include -#ifdef STA_STM32_UART_ENABLED - -#include - - -namespace sta -{ - STM32UART::STM32UART(UART_HandleTypeDef * handle) - : handle_{handle} - { - STA_ASSERT(handle != nullptr); - } - - - void STM32UART::write(const uint8_t * buffer, size_t size) - { - STA_ASSERT(buffer != nullptr); - - HAL_UART_Transmit(handle_, const_cast(buffer), size, HAL_MAX_DELAY); - } -} // namespace sta - - -#endif // STA_STM32_UART_ENABLED diff --git a/src/uart.cpp b/src/uart.cpp deleted file mode 100644 index 87eadef..0000000 --- a/src/uart.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include - -#include - -#include -#include - - - -namespace sta -{ - void UART::write(uint8_t value) - { - // TODO Handle endian-ness - write(&value, 1); - } - - void UART::write(uint16_t value) - { - // TODO Handle endian-ness - write(reinterpret_cast(&value), sizeof(value)); - } - - void UART::write(uint32_t value) - { - // TODO Handle endian-ness - write(reinterpret_cast(&value), sizeof(value)); - } -} // namespace sta