#include #include #include namespace { inline std::uint32_t port_mode_register (const std::uint32_t port) { return std::uint32_t(port + 0x00UL); } inline std::uint32_t output_type_register (const std::uint32_t port) { return std::uint32_t(port + 0x04UL); } inline std::uint32_t output_speed_register (const std::uint32_t port) { return std::uint32_t(port + 0x08UL); } inline std::uint32_t pull_up_pull_down_register(const std::uint32_t port) { return std::uint32_t(port + 0x0CUL); } inline std::uint32_t input_data_register (const std::uint32_t port) { return std::uint32_t(port + 0x10UL); } inline std::uint32_t output_data_register (const std::uint32_t port) { return std::uint32_t(port + 0x14UL); } void set_direction_output(const std::uint32_t port, const std::uint32_t bpos) { // Set the port pin control bits. // Set for no pull up, no pull down. mcal::reg::dynamic_access::reg_and(pull_up_pull_down_register(port), ~static_cast(UINT32_C(0x03) << (bpos * 2U))); // Select the fastest output speed. mcal::reg::dynamic_access::reg_or(output_speed_register(port), static_cast(UINT32_C(0x03) << (bpos * 2U))); // Set the port pin to push-pull output type. mcal::reg::dynamic_access::bit_clr(output_type_register(port), bpos); // Set the port pin direction to digital output. mcal::reg::dynamic_access::reg_or(port_mode_register(port), static_cast(UINT32_C(0x01) << (bpos * 2U))); } #if 0 void set_direction_input(const std::uint32_t port, const std::uint32_t bpos) { // Set the port pin direction to digital input. mcal::reg::dynamic_access::reg_and(port_mode_register(port), ~static_cast(UINT32_C(0x03) << (bpos * 2U))); } #endif void set_pin_high(const std::uint32_t port, const std::uint32_t bpos) { // Set the port output value to high. mcal::reg::dynamic_access::bit_set(output_data_register(port), bpos); } void set_pin_low(const std::uint32_t port, const std::uint32_t bpos) { // Set the port output value to low. mcal::reg::dynamic_access::bit_clr(output_data_register(port), bpos); } bool read_input_value(const std::uint32_t port, const std::uint32_t bpos) { // Read the port input value. // According to the microcontroller handbook: // "These bits are read-only and can be accessed in *word* mode only, ..." // We, therefore, access this register with a 16-bit address-type // template parameter. return mcal::reg::dynamic_access::bit_get(input_data_register(port), bpos); } } extern "C" void Dio_Init(const Dio_ConfigType*) { set_direction_output(mcal::reg::gpioa_base, 5U); set_direction_output(mcal::reg::gpioc_base, 8U); } extern "C" void Dio_WriteChannel(Dio_ChannelType ChannelId, Dio_LevelType Level) { (Level != STD_LOW ? set_pin_high(mcal::reg::gpioa_base + std::uint32_t((ChannelId >> 8U) * 0x0400U), ChannelId & 0xFU) : set_pin_low (mcal::reg::gpioa_base + std::uint32_t((ChannelId >> 8U) * 0x0400U), ChannelId & 0xFU)); } extern "C" Dio_LevelType Dio_ReadChannel(Dio_ChannelType ChannelId) { const bool pin_is_high = read_input_value(mcal::reg::gpioa_base + std::uint32_t((ChannelId >> 8U) * 0x0400U), ChannelId & 0xFU); return (pin_is_high ? STD_HIGH : STD_LOW); }