Rebase onto main + clean up the code a bit
parent
fce2195558
commit
6cb072ce79
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
#include "adc.h"
|
||||||
|
|
||||||
|
namespace hal {
|
||||||
|
namespace adc {
|
||||||
|
|
||||||
|
uint16_t ReadADC(uint8_t adc) { return 0; }
|
||||||
|
|
||||||
|
} // namespace adc
|
||||||
|
} // namespace hal
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
|
||||||
34
src/main.cpp
34
src/main.cpp
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue