Rebase onto main + clean up the code a bit

pull/13/head
D.R.racer 2021-05-25 11:55:28 +02:00
parent fce2195558
commit 6cb072ce79
5 changed files with 184 additions and 154 deletions

View File

@ -183,8 +183,14 @@ target_include_directories(firmware PRIVATE include src)
target_compile_options(firmware PRIVATE -Wdouble-promotion) target_compile_options(firmware PRIVATE -Wdouble-promotion)
target_sources( target_sources(
firmware PRIVATE src/main.cpp src/hal/avr/cpu.cpp src/hal/avr/usart.cpp src/modules/protocol.cpp firmware
src/modules/buttons.cpp src/modules/leds.cpp PRIVATE src/main.cpp
src/hal/avr/cpu.cpp
src/hal/avr/usart.cpp
src/hal/adc.cpp
src/modules/protocol.cpp
src/modules/buttons.cpp
src/modules/leds.cpp
) )
set_property( set_property(

9
src/hal/adc.cpp Normal file
View File

@ -0,0 +1,9 @@
#include "adc.h"
namespace hal {
namespace adc {
uint16_t ReadADC(uint8_t adc) { return 0; }
} // namespace adc
} // namespace hal

View File

@ -1,13 +1,18 @@
#include "../usart.h" #include "../usart.h"
#include <avr/interrupt.h> #include <avr/interrupt.h>
uint8_t hal::USART::Read() { namespace hal {
uint8_t c = 0; namespace usart {
this->rx_buf.ConsumeFirst(c);
return c;
}
void hal::USART::Write(uint8_t c) { USART usart1;
uint8_t USART::Read() {
uint8_t c = 0;
rx_buf.ConsumeFirst(c);
return c;
}
void USART::Write(uint8_t c) {
_written = true; _written = true;
// If the buffer and the data register is empty, just write the byte // If the buffer and the data register is empty, just write the byte
// to the data register and be done. This shortcut helps // to the data register and be done. This shortcut helps
@ -27,46 +32,51 @@ void hal::USART::Write(uint8_t c) {
// register empty flag ourselves. If it is set, pretend an // register empty flag ourselves. If it is set, pretend an
// interrupt has happened and call the handler to free up // interrupt has happened and call the handler to free up
// space for us. // space for us.
if (husart->UCSRxA & (1 << 5)) if (husart->UCSRxA & (1 << 5)) {
ISR_UDRE(); ISR_UDRE();
}
} else { } else {
// nop, the interrupt handler will free up space for us // nop, the interrupt handler will free up space for us
} }
} }
husart->UCSRxB |= (1 << 5); //enable UDRE interrupt husart->UCSRxB |= (1 << 5); //enable UDRE interrupt
} }
void hal::USART::Flush() { void USART::Flush() {
// If we have never written a byte, no need to flush. This special // If we have never written a byte, no need to flush. This special
// case is needed since there is no way to force the TXC (transmit // case is needed since there is no way to force the TXC (transmit
// complete) bit to 1 during initialization // complete) bit to 1 during initialization
if (!_written) if (!_written) {
return; return;
}
while ((husart->UCSRxB & (1 << 5)) || ~(husart->UCSRxA & (1 << 6))) { while ((husart->UCSRxB & (1 << 5)) || ~(husart->UCSRxA & (1 << 6))) {
if (bit_is_clear(SREG, SREG_I) && (husart->UCSRxB & (1 << 5))) if (bit_is_clear(SREG, SREG_I) && (husart->UCSRxB & (1 << 5)))
// Interrupts are globally disabled, but the DR empty // Interrupts are globally disabled, but the DR empty
// interrupt should be enabled, so poll the DR empty flag to // interrupt should be enabled, so poll the DR empty flag to
// prevent deadlock // prevent deadlock
if (husart->UCSRxA & (1 << 5)) if (husart->UCSRxA & (1 << 5)) {
ISR_UDRE(); ISR_UDRE();
} }
}
// If we get here, nothing is queued anymore (DRIE is disabled) and // If we get here, nothing is queued anymore (DRIE is disabled) and
// the hardware finished tranmission (TXC is set). // the hardware finished tranmission (TXC is set).
} }
void hal::USART::puts(const char *str) { void USART::puts(const char *str) {
while (*str) while (*str) {
this->Write(*str++); Write(*str++);
} }
}
hal::USART usart1(USART1); } // namespace usart
} // namespace hal
ISR(USART1_RX_vect) { ISR(USART1_RX_vect) {
usart1.ISR_RX(); hal::usart::usart1.ISR_RX();
} }
ISR(USART1_UDRE_vect) { ISR(USART1_UDRE_vect) {
usart1.ISR_UDRE(); hal::usart::usart1.ISR_UDRE();
} }

View File

@ -8,8 +8,10 @@
/// for >1 USART interfaces /// for >1 USART interfaces
namespace hal { namespace hal {
class USART { namespace usart {
public:
class USART {
public:
struct USART_TypeDef { struct USART_TypeDef {
volatile uint8_t UCSRxA; volatile uint8_t UCSRxA;
volatile uint8_t UCSRxB; volatile uint8_t UCSRxB;
@ -81,19 +83,24 @@ public:
husart->UCSRxB &= ~(1 << 5); // disable UDRE interrupt husart->UCSRxB &= ~(1 << 5); // disable UDRE interrupt
} }
USART(USART_TypeDef *husart) USART() = default;
: husart(husart) {}; void Init(USART_TypeDef *conf) {
husart = conf;
}
private: private:
// IO base address // IO base address
USART_TypeDef *husart; USART_TypeDef *husart;
bool _written; bool _written;
CircleBuffer<uint8_t, 32> tx_buf; CircleBuffer<uint8_t, 32> tx_buf;
CircleBuffer<uint8_t, 32> rx_buf; CircleBuffer<uint8_t, 32> rx_buf;
}; };
/// beware - normally we'd make a singleton, but avr-gcc generates suboptimal code for them, therefore we only keep this extern variable
extern USART usart1;
} // namespace usart
} // namespace hal } // namespace hal
#define USART1 ((hal::USART::USART_TypeDef *)&UCSR1A) #define USART1 ((hal::USART::USART_TypeDef *)&UCSR1A)
extern hal::USART usart1;

View File

@ -13,8 +13,6 @@
#include "logic/mm_control.h" #include "logic/mm_control.h"
static hal::UART uart;
static modules::protocol::Protocol protocol; static modules::protocol::Protocol protocol;
static modules::buttons::Buttons buttons; static modules::buttons::Buttons buttons;
static modules::leds::LEDs leds; static modules::leds::LEDs leds;
@ -49,17 +47,17 @@ void TmpPlayground() {
// break; // break;
sei(); sei();
usart1.puts("1234567890\n"); hal::usart::usart1.puts("1234567890\n");
usart1.puts("1234567890\n"); hal::usart::usart1.puts("1234567890\n");
usart1.puts("1234567890\n"); hal::usart::usart1.puts("1234567890\n");
usart1.puts("1234567890\n"); hal::usart::usart1.puts("1234567890\n");
usart1.puts("1234567890\n"); hal::usart::usart1.puts("1234567890\n");
usart1.puts("1234567890\n"); hal::usart::usart1.puts("1234567890\n");
usart1.puts("1234567890\n"); hal::usart::usart1.puts("1234567890\n");
usart1.puts("1234567890\n"); hal::usart::usart1.puts("1234567890\n");
usart1.puts("1234567890\n"); hal::usart::usart1.puts("1234567890\n");
usart1.puts("1234567890\n"); hal::usart::usart1.puts("1234567890\n");
usart1.puts("1234567890\n"); hal::usart::usart1.puts("1234567890\n");
} }
/// One-time setup of HW and SW components /// One-time setup of HW and SW components
@ -76,12 +74,12 @@ void setup() {
// @@TODO if the shift register doesn't work we really can't signalize anything, only internal variables will be accessible if the UART works // @@TODO if the shift register doesn't work we really can't signalize anything, only internal variables will be accessible if the UART works
USART::USART_InitTypeDef usart_conf = { hal::usart::USART::USART_InitTypeDef usart_conf = {
.rx_pin = gpio::GPIO_pin(GPIOD, 2), .rx_pin = gpio::GPIO_pin(GPIOD, 2),
.tx_pin = gpio::GPIO_pin(GPIOD, 3), .tx_pin = gpio::GPIO_pin(GPIOD, 3),
.baudrate = 115200, .baudrate = 115200,
usart1.Init(&usart_conf); };
hal::usart::usart1.Init(&usart_conf);
leds.SetMode(3, false, modules::leds::Mode::on); leds.SetMode(3, false, modules::leds::Mode::on);
// shr::Send(leds.Step(0)); // shr::Send(leds.Step(0));
@ -115,8 +113,8 @@ void ProcessRequestMsg(const modules::protocol::RequestMsg &rq) {
/// @returns true if a request was successfully finished /// @returns true if a request was successfully finished
bool CheckMsgs() { bool CheckMsgs() {
using mpd = modules::protocol::DecodeStatus; using mpd = modules::protocol::DecodeStatus;
while (!uart.ReadEmpty()) { while (!hal::usart::usart1.ReadEmpty()) {
switch (protocol.DecodeRequest(uart.Read())) { switch (protocol.DecodeRequest(hal::usart::usart1.Read())) {
case mpd::MessageCompleted: case mpd::MessageCompleted:
// process the input message // process the input message
return true; return true;