diff --git a/Mainboard/Firmware/README.md b/Mainboard/Firmware/README.md
index b05666ef..d69aa095 100644
--- a/Mainboard/Firmware/README.md
+++ b/Mainboard/Firmware/README.md
@@ -20,30 +20,20 @@ This tool is analogous to the Xilinx SDK tool (for the AMDC). It is effectively
To develop code for STM32 processors:
-#### Generating New Projects
+### Testing / Debugging Code
-1. Use the STM32CubeIDE to generate a new project
-2. When configuring this project, select the exact MCU device which you are targetting (the mainboard uses `STM32F765ZGT6`)
-3. Open the CubeMX perspective (i.e. `*.ioc` file) and configure all desired peripherals (SPIs, UARTs, ETH, etc)
-4. Change to the clock configuration tab and use the GUI to configure the PLL settings
-5. Generate initialization code to boot-strap your project. This will configure the clock and peripherals like you specified.
+1. Use the IDE to compile your code and ensure there are no errors.
+2. To flash the hardware, plug in a SWD debugger device to your PC + board (highly recommend [`STLINK-V3SET`](https://www.digikey.com/product-detail/en/stmicroelectronics/STLINK-V3SET/497-18216-ND/9636028))
+3. Configure a debug session in the IDE
+4. Run the debug sessions. This will flash the MCU and start the code (probably breakpoint at `main()`)
-#### Writing Code
-
-6. Now that you have a base project, write all your application-specific code...
-
-#### Testing / Debugging Code
-
-7. Use the IDE to compile your code and ensure there are no errors.
-8. To flash the hardware, plug in a SWD debugger device to your PC + board (highly recommend [`STLINK-V3SET`](https://www.digikey.com/product-detail/en/stmicroelectronics/STLINK-V3SET/497-18216-ND/9636028))
-9. Configure a debug session in the IDE
-10. Run the debug sessions. This will flash the MCU and start the code (probably breakpoint at `main()`)
+For more detailed instructions on programming the AMDS, please refer to the [AMDS Documentation](https://docs.amdc.dev/accessories/amds/index.html).
NOTE: The STM32 devices are typically programmed into non-volatile memory. Therefore, there is no seperate "flashing" step. Every time you upload code, it is permanantely stored on the processor. You can power cycle the device and your code will start running again.
## Mainboard Firmware Design
-The mainboard firmware is fairly simple, yet very specialized for the application. Before changing *anything* in the code, make sure you understand how it works. Practically every line of the code is optimized for speed and efficiency! Using a multi-channel logic analyzer / oscilloscope is absolutely required when updating the mainboard firmware to validate code timing.
+The mainboard firmware is fairly simple, yet very specialized for the application. Before changing *anything* in the code, make sure you understand how it works. Practically every line of the code is optimized for speed and efficiency! Using a multi-channel logic analyzer / oscilloscope is absolutely required when updating the mainboard firmware to validate code timing. Please refer to the [Firmware Architecture Documentation](https://docs.amdc.dev/accessories/amds/firmware/index.html) for more information.
**Do not blindly change the code.**
diff --git a/Mainboard/Firmware/motherboard_v1/.clang-format b/Mainboard/Firmware/mainboard/.clang-format
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/.clang-format
rename to Mainboard/Firmware/mainboard/.clang-format
diff --git a/Mainboard/Firmware/mainboard/.cproject b/Mainboard/Firmware/mainboard/.cproject
new file mode 100644
index 00000000..49f12ee3
--- /dev/null
+++ b/Mainboard/Firmware/mainboard/.cproject
@@ -0,0 +1,379 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Mainboard/Firmware/motherboard_v1/.github/workflows/main.yml b/Mainboard/Firmware/mainboard/.github/workflows/main.yml
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/.github/workflows/main.yml
rename to Mainboard/Firmware/mainboard/.github/workflows/main.yml
diff --git a/Mainboard/Firmware/motherboard_v1/.gitignore b/Mainboard/Firmware/mainboard/.gitignore
similarity index 94%
rename from Mainboard/Firmware/motherboard_v1/.gitignore
rename to Mainboard/Firmware/mainboard/.gitignore
index 48daa56e..bf95e117 100644
--- a/Mainboard/Firmware/motherboard_v1/.gitignore
+++ b/Mainboard/Firmware/mainboard/.gitignore
@@ -1,6 +1,8 @@
.settings/language.settings.xml
Debug/
Release/
+AMDS/
+2S/
scripts/__pycache__/
*.o
*.d
diff --git a/Mainboard/Firmware/motherboard_v1/.mxproject b/Mainboard/Firmware/mainboard/.mxproject
similarity index 92%
rename from Mainboard/Firmware/motherboard_v1/.mxproject
rename to Mainboard/Firmware/mainboard/.mxproject
index 1612937d..d510d269 100644
--- a/Mainboard/Firmware/motherboard_v1/.mxproject
+++ b/Mainboard/Firmware/mainboard/.mxproject
@@ -9,25 +9,25 @@ CDefines=USE_HAL_DRIVER;STM32F765xx;USE_HAL_DRIVER;USE_HAL_DRIVER;
[PreviousGenFiles]
AdvancedFolderStructure=true
HeaderFileListSize=7
-HeaderFiles#0=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/motherboard_v1/Core/Inc/gpio.h
-HeaderFiles#1=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/motherboard_v1/Core/Inc/i2c.h
-HeaderFiles#2=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/motherboard_v1/Core/Inc/spi.h
-HeaderFiles#3=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/motherboard_v1/Core/Inc/usart.h
-HeaderFiles#4=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/motherboard_v1/Core/Inc/stm32f7xx_it.h
-HeaderFiles#5=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/motherboard_v1/Core/Inc/stm32f7xx_hal_conf.h
-HeaderFiles#6=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/motherboard_v1/Core/Inc/main.h
+HeaderFiles#0=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/mainboard/Core/Inc/gpio.h
+HeaderFiles#1=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/mainboard/Core/Inc/i2c.h
+HeaderFiles#2=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/mainboard/Core/Inc/spi.h
+HeaderFiles#3=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/mainboard/Core/Inc/usart.h
+HeaderFiles#4=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/mainboard/Core/Inc/stm32f7xx_it.h
+HeaderFiles#5=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/mainboard/Core/Inc/stm32f7xx_hal_conf.h
+HeaderFiles#6=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/mainboard/Core/Inc/main.h
HeaderFolderListSize=1
-HeaderPath#0=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/motherboard_v1/Core/Inc
+HeaderPath#0=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/mainboard/Core/Inc
HeaderFiles=;
SourceFileListSize=7
-SourceFiles#0=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/motherboard_v1/Core/Src/gpio.c
-SourceFiles#1=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/motherboard_v1/Core/Src/i2c.c
-SourceFiles#2=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/motherboard_v1/Core/Src/spi.c
-SourceFiles#3=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/motherboard_v1/Core/Src/usart.c
-SourceFiles#4=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/motherboard_v1/Core/Src/stm32f7xx_it.c
-SourceFiles#5=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/motherboard_v1/Core/Src/stm32f7xx_hal_msp.c
-SourceFiles#6=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/motherboard_v1/Core/Src/main.c
+SourceFiles#0=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/mainboard/Core/Src/gpio.c
+SourceFiles#1=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/mainboard/Core/Src/i2c.c
+SourceFiles#2=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/mainboard/Core/Src/spi.c
+SourceFiles#3=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/mainboard/Core/Src/usart.c
+SourceFiles#4=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/mainboard/Core/Src/stm32f7xx_it.c
+SourceFiles#5=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/mainboard/Core/Src/stm32f7xx_hal_msp.c
+SourceFiles#6=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/mainboard/Core/Src/main.c
SourceFolderListSize=1
-SourcePath#0=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/motherboard_v1/Core/Src
+SourcePath#0=C:/Users/npetersen2/STM32CubeIDE/workspace_1.3.0/mainboard/Core/Src
SourceFiles=;
diff --git a/Mainboard/Firmware/motherboard_v1/.project b/Mainboard/Firmware/mainboard/.project
similarity index 97%
rename from Mainboard/Firmware/motherboard_v1/.project
rename to Mainboard/Firmware/mainboard/.project
index ce44526f..46f68d3f 100644
--- a/Mainboard/Firmware/motherboard_v1/.project
+++ b/Mainboard/Firmware/mainboard/.project
@@ -1,6 +1,6 @@
- motherboard_v1
+ mainboard
diff --git a/Mainboard/Firmware/mainboard/.settings/com.st.stm32cube.ide.mcu.sfrview.prefs b/Mainboard/Firmware/mainboard/.settings/com.st.stm32cube.ide.mcu.sfrview.prefs
new file mode 100644
index 00000000..98a69fc7
--- /dev/null
+++ b/Mainboard/Firmware/mainboard/.settings/com.st.stm32cube.ide.mcu.sfrview.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+sfrviewstate={"fFavorites"\:{"fLists"\:{}},"fProperties"\:{"fNodeProperties"\:{}}}
diff --git a/Mainboard/Firmware/mainboard/.settings/stm32cubeide.project.prefs b/Mainboard/Firmware/mainboard/.settings/stm32cubeide.project.prefs
new file mode 100644
index 00000000..5064fdc4
--- /dev/null
+++ b/Mainboard/Firmware/mainboard/.settings/stm32cubeide.project.prefs
@@ -0,0 +1,4 @@
+2F62501ED4689FB349E356AB974DBE57=DB4D67F16CA069769A3F87733D593AF2
+8DF89ED150041C4CBC7CB9A9CAA90856=DB4D67F16CA069769A3F87733D593AF2
+DC22A860405A8BF2F2C095E5B6529F12=D1E96F3EE32E2AB2CF91940507FB3624
+eclipse.preferences.version=1
diff --git a/Mainboard/Firmware/mainboard/Core/Inc/adc.h b/Mainboard/Firmware/mainboard/Core/Inc/adc.h
new file mode 100644
index 00000000..c26e14b9
--- /dev/null
+++ b/Mainboard/Firmware/mainboard/Core/Inc/adc.h
@@ -0,0 +1,9 @@
+#ifndef ADC_H
+#define ADC_H
+
+#include
+
+void adc_init(void);
+
+
+#endif // ADC_H
diff --git a/Mainboard/Firmware/motherboard_v1/Core/Inc/defines.h b/Mainboard/Firmware/mainboard/Core/Inc/defines.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Core/Inc/defines.h
rename to Mainboard/Firmware/mainboard/Core/Inc/defines.h
diff --git a/Mainboard/Firmware/motherboard_v1/Core/Inc/drv_clock.h b/Mainboard/Firmware/mainboard/Core/Inc/drv_clock.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Core/Inc/drv_clock.h
rename to Mainboard/Firmware/mainboard/Core/Inc/drv_clock.h
diff --git a/Mainboard/Firmware/motherboard_v1/Core/Inc/drv_gpio.h b/Mainboard/Firmware/mainboard/Core/Inc/drv_gpio.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Core/Inc/drv_gpio.h
rename to Mainboard/Firmware/mainboard/Core/Inc/drv_gpio.h
diff --git a/Mainboard/Firmware/motherboard_v1/Core/Inc/drv_i2c.h b/Mainboard/Firmware/mainboard/Core/Inc/drv_i2c.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Core/Inc/drv_i2c.h
rename to Mainboard/Firmware/mainboard/Core/Inc/drv_i2c.h
diff --git a/Mainboard/Firmware/motherboard_v1/Core/Inc/drv_led.h b/Mainboard/Firmware/mainboard/Core/Inc/drv_led.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Core/Inc/drv_led.h
rename to Mainboard/Firmware/mainboard/Core/Inc/drv_led.h
diff --git a/Mainboard/Firmware/motherboard_v1/Core/Inc/drv_spi.h b/Mainboard/Firmware/mainboard/Core/Inc/drv_spi.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Core/Inc/drv_spi.h
rename to Mainboard/Firmware/mainboard/Core/Inc/drv_spi.h
diff --git a/Mainboard/Firmware/mainboard/Core/Inc/drv_uart.h b/Mainboard/Firmware/mainboard/Core/Inc/drv_uart.h
new file mode 100644
index 00000000..358e0bd6
--- /dev/null
+++ b/Mainboard/Firmware/mainboard/Core/Inc/drv_uart.h
@@ -0,0 +1,151 @@
+#ifndef DRV_UART_H
+#define DRV_UART_H
+
+// BENCHMARK MODE FLAG for DMA
+//#define BENCHMARK_MODE
+
+#include "platform.h"
+#include
+#include
+
+void drv_uart_init(void);
+
+extern UART_HandleTypeDef huart2;
+extern UART_HandleTypeDef huart3;
+
+extern UART_HandleTypeDef DAISY_RX1_UART;
+extern UART_HandleTypeDef DAISY_RX2_UART;
+
+extern DMA_HandleTypeDef hdma_uart4_rx;
+extern DMA_HandleTypeDef hdma_uart5_rx;
+
+extern DMA_HandleTypeDef hdma_uart6_rx;
+extern DMA_HandleTypeDef hdma_uart1_rx;
+
+typedef enum {
+ STATE_IDLE,
+ STATE_GOT_HEADER,
+ STATE_GOT_MSB
+} rx_state_t;
+
+typedef struct {
+ rx_state_t state;
+ uint8_t header;
+ uint8_t data[2];
+ uint8_t read_index;
+} uart_rx_tracker_t;
+
+extern uart_rx_tracker_t tracker1;
+extern uart_rx_tracker_t tracker2;
+
+#define AMDS_RX_BUF_SIZE 256 // Must be 256 for uint8_t indexing and wrap-around logic to work correctly
+extern uint8_t DAISY_RX1_Pool[AMDS_RX_BUF_SIZE];
+extern uint8_t DAISY_RX2_Pool[AMDS_RX_BUF_SIZE];
+
+#ifdef BENCHMARK_MODE
+extern volatile uint8_t mock_dma_write_head;
+#endif
+
+// Declare the global flag so all .c files know it exists
+extern volatile bool is_routing_active;
+
+bool drv_uart_has_dma_data(void);
+
+#define GPIO_TOGGLE_PIN(port, pin) ((port)->BSRR = ((port)->ODR & (pin)) ? ((pin) << 16) : (pin))
+
+void process_routing(void);
+
+/**
+ * Thread-safe, non-blocking wrapper for process_routing().
+ * Uses an atomic try-lock to prevent reentrancy without
+ * stalling the CPU or blinding interrupts for too long.
+ */
+static inline void try_process_routing(void) {
+ // 1. Enter brief critical section (approx. 3 CPU cycles)
+ __disable_irq();
+
+ // 2. Check if the lock is already claimed
+ if (is_routing_active) {
+ // Someone else is already routing. Safely abort.
+ __enable_irq();
+ return;
+ }
+
+ // 3. Claim the lock
+ is_routing_active = true;
+
+ // 4. Exit critical section BEFORE the heavy lifting
+ __enable_irq();
+
+ // 5. Perform the actual routing with interrupts perfectly active
+ process_routing();
+
+ // 6. Release the lock when finished
+ // (This single write is inherently atomic on a 32-bit ARM core,
+ // so we don't need to disable interrupts just to clear it).
+ is_routing_active = false;
+}
+
+/**
+ * Attempt to instantly reset the routing state machine and flush buffers.
+ * To be called ONLY from the very beginning of EXTI3_IRQHandler.
+ */
+static inline void try_reset_routing_state(void) {
+ // Because we are inside an IRQ, we preempted main().
+ // We do NOT need to disable interrupts here to check the flag safely.
+ if (!is_routing_active) {
+
+ // 1. Reset state machines to gracefully await the next packet
+ tracker1.state = STATE_IDLE;
+ tracker2.state = STATE_IDLE;
+
+ // 2. Soft-flush the DMA buffers.
+ // We advance our read pointers to exactly where the DMA hardware
+ // is currently writing. All old, unprocessed bytes are instantly discarded.
+#ifdef BENCHMARK_MODE
+ tracker1.read_index = mock_dma_write_head;
+ tracker2.read_index = mock_dma_write_head;
+#else
+ tracker1.read_index = (uint8_t)(AMDS_RX_BUF_SIZE - __HAL_DMA_GET_COUNTER(DAISY_RX1_UART.hdmarx));
+ tracker2.read_index = (uint8_t)(AMDS_RX_BUF_SIZE - __HAL_DMA_GET_COUNTER(DAISY_RX2_UART.hdmarx));
+#endif
+ }
+}
+
+static inline void drv_uart_putc_fast(USART_TypeDef *uart, uint8_t data)
+{
+ // Wait until UART is ready to accept next character
+ while (!(uart->ISR & UART_FLAG_TXE)) {
+ asm("nop");
+ }
+
+ // Load the TDR register to send a character
+ uart->TDR = data;
+}
+
+static inline void drv_uart_wait_TC(USART_TypeDef *uart)
+{
+ // ONLY USE THIS IF DISABLING THE UART OR GOING TO SLEEP!
+ // This function waits for all data to be sent from the USART
+ // (it waits for both the TDR and the Shift Register to be
+ // completely empty)
+ //
+ // Do NOT USE THIS during normal continuous data transmission
+ // as it will add significant delays
+ while (!(uart->ISR & UART_FLAG_TC)) {
+ asm("nop");
+ }
+}
+
+static inline void drv_uart_send_fast(USART_TypeDef *uart, uint8_t *data, uint16_t len)
+{
+ while (len > 0) {
+ drv_uart_putc_fast(uart, *data);
+ data++;
+ len--;
+ }
+
+ drv_uart_wait_TC(uart);
+}
+
+#endif // DRV_UART_H
diff --git a/Mainboard/Firmware/motherboard_v1/Core/Inc/platform.h b/Mainboard/Firmware/mainboard/Core/Inc/platform.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Core/Inc/platform.h
rename to Mainboard/Firmware/mainboard/Core/Inc/platform.h
diff --git a/Mainboard/Firmware/motherboard_v1/Core/Inc/stm32f7xx_hal_conf.h b/Mainboard/Firmware/mainboard/Core/Inc/stm32f7xx_hal_conf.h
similarity index 99%
rename from Mainboard/Firmware/motherboard_v1/Core/Inc/stm32f7xx_hal_conf.h
rename to Mainboard/Firmware/mainboard/Core/Inc/stm32f7xx_hal_conf.h
index 904591ed..6015fb97 100644
--- a/Mainboard/Firmware/motherboard_v1/Core/Inc/stm32f7xx_hal_conf.h
+++ b/Mainboard/Firmware/mainboard/Core/Inc/stm32f7xx_hal_conf.h
@@ -151,6 +151,7 @@
#define USE_RTOS 0U
#define PREFETCH_ENABLE 0U
#define ART_ACCLERATOR_ENABLE 0U /* To enable instruction cache and prefetch */
+#define USE_HAL_UART_REGISTER_CALLBACKS 1U /* UART register callback disabled */
/* ########################## Assert Selection ############################## */
/**
diff --git a/Mainboard/Firmware/motherboard_v1/Core/Inc/stm32f7xx_it.h b/Mainboard/Firmware/mainboard/Core/Inc/stm32f7xx_it.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Core/Inc/stm32f7xx_it.h
rename to Mainboard/Firmware/mainboard/Core/Inc/stm32f7xx_it.h
diff --git a/Mainboard/Firmware/mainboard/Core/Src/adc.c b/Mainboard/Firmware/mainboard/Core/Src/adc.c
new file mode 100644
index 00000000..92abcd83
--- /dev/null
+++ b/Mainboard/Firmware/mainboard/Core/Src/adc.c
@@ -0,0 +1,571 @@
+#include "adc.h"
+#include "drv_uart.h"
+#include "drv_spi.h"
+#include "platform.h"
+#include
+#include
+
+static void setup_pin_SYNC_ADC(void);
+static void setup_pin_CONVST(void);
+
+// clang-format off
+
+#define NOP1 asm("nop")
+#define NOP2 NOP1;NOP1
+#define NOP4 NOP2;NOP2
+#define NOP8 NOP4;NOP4
+#define NOP16 NOP8;NOP8
+#define NOP32 NOP16;NOP16
+#define NOP64 NOP32;NOP32
+#define NOP128 NOP64;NOP64
+#define NOP256 NOP128;NOP128
+
+// clang-format on
+
+#define GPIO_SET_PIN(port, pin, x) port->BSRR = (x) ? pin : (pin << 16)
+#define GPIO_TOGGLE_PIN(port, pin) ((port)->BSRR = ((port)->ODR & (pin)) ? ((pin) << 16) : (pin))
+
+#define SET_PIN_CONVST12_HIGH GPIO_SET_PIN(GPIOE, GPIO_PIN_10, 1)
+#define SET_PIN_CONVST34_HIGH GPIO_SET_PIN(GPIOE, GPIO_PIN_11, 1)
+#define SET_PIN_CONVST56_HIGH GPIO_SET_PIN(GPIOF, GPIO_PIN_6, 1)
+#define SET_PIN_CONVST78_HIGH GPIO_SET_PIN(GPIOG, GPIO_PIN_8, 1)
+
+#define SET_PIN_CONVST12_LOW GPIO_SET_PIN(GPIOE, GPIO_PIN_10, 0)
+#define SET_PIN_CONVST34_LOW GPIO_SET_PIN(GPIOE, GPIO_PIN_11, 0)
+#define SET_PIN_CONVST56_LOW GPIO_SET_PIN(GPIOF, GPIO_PIN_6, 0)
+#define SET_PIN_CONVST78_LOW GPIO_SET_PIN(GPIOG, GPIO_PIN_8, 0)
+
+#define ADC_FULL_SCALE (1 << 15)
+#define ADC_REF_VOLTAGE (4.096)
+#define ADC_VOLTS_PER_BIT ((float) ADC_REF_VOLTAGE / (float) ADC_FULL_SCALE)
+
+#define ADC_BITS_TO_VOLTS(bits) (ADC_VOLTS_PER_BIT * (float) bits)
+
+
+// Global bitmask: 1 = Active, 0 = Inactive.
+// For example: 0b00001111 (0x0F) means channels 1-4 are active, 5-8 are disabled.
+#if defined(TARGET_AMDS)
+ volatile uint8_t active_sensor_mask = 0xFF;
+#elif defined(TARGET_2S)
+ volatile uint8_t active_sensor_mask = 0x11;
+#else
+ #error "Please define a target board (TARGET_AMDS or TARGET_2S)!"
+#endif
+
+void adc_init(void)
+{
+ // Setup output pin which starts ADC conversions
+ setup_pin_CONVST();
+
+ // Setup input pin which triggers ADC sampling (from AMDC)
+ setup_pin_SYNC_ADC();
+}
+
+#if defined(TARGET_AMDS)
+
+static void adc_sample_all_daughtercards(uint16_t *sample_data_out)
+{
+ // This function has been optimized for very
+ // fast operation of all four SPI interfaces
+ // to the daughter cards.
+ //
+ // It directly manipulates the four SPI peripherals'
+ // registers to read in data from the ADCs. The ordering
+ // of operations may look strange, but this is to minimize
+ // wait time of the various APB interconnects in the MCU.
+ //
+ // The ADC devices support a max of 400ksps. Looking at
+ // the waveforms from this function, the CONVST line is
+ // asserted for effectively 280kHz... It could be faster,
+ // but its not terrible...
+
+ // Start all ADC conversions. We start them in order since
+ // the ADC connected to CONVST12 will probably get done first.
+ //
+ // ADC conversion triggered by CONVST12 connects to SPI1
+ // ADC conversion triggered by CONVST34 connects to SPI4
+ // ADC conversion triggered by CONVST56 connects to SPI5
+ // ADC conversion triggered by CONVST78 connects to SPI6
+ SET_PIN_CONVST12_HIGH;
+ SET_PIN_CONVST34_HIGH;
+ SET_PIN_CONVST56_HIGH;
+ SET_PIN_CONVST78_HIGH;
+
+ // Wait for ADC conversion to complete (per datasheet, >= 1300ns
+ // Each NOP takes 5ns, unrolled so branches don't affect timing...
+ //
+ // We need 260 NOPs
+ NOP256;
+ NOP4;
+
+ // Smartly read all data from all ADCs at the same time.
+ // This starts all the SPI peripherals effectively in parallel,
+ // then waits for them to complete and gets the resulting data.
+
+ // Start the SCLKs
+ drv_spi_start_read_two_16bits(SPI1);
+ drv_spi_start_read_two_16bits(SPI4);
+ drv_spi_start_read_two_16bits(SPI5);
+ drv_spi_start_read_two_16bits(SPI6);
+
+ // Wait and read first ADC data
+ //
+ // The strange ordering of sample data indexing is
+ // to correct for PCB layout pin swapping issues.
+ drv_spi_finish_read_one_16bits(SPI1, &sample_data_out[3]);
+ drv_spi_finish_read_one_16bits(SPI4, &sample_data_out[1]);
+ drv_spi_finish_read_one_16bits(SPI5, &sample_data_out[0]);
+ drv_spi_finish_read_one_16bits(SPI6, &sample_data_out[2]);
+
+ // Wait for second ADC data to complete
+ drv_spi_wait_for_RX(SPI1);
+ drv_spi_wait_for_RX(SPI4);
+ drv_spi_wait_for_RX(SPI5);
+ drv_spi_wait_for_RX(SPI6);
+
+ // End conversion
+ SET_PIN_CONVST12_LOW;
+ SET_PIN_CONVST34_LOW;
+ SET_PIN_CONVST56_LOW;
+ SET_PIN_CONVST78_LOW;
+
+ // Read second ADC data
+ drv_spi_get_DR(SPI1, &sample_data_out[7]);
+ drv_spi_get_DR(SPI4, &sample_data_out[5]);
+ drv_spi_get_DR(SPI5, &sample_data_out[4]);
+ drv_spi_get_DR(SPI6, &sample_data_out[6]);
+}
+
+void adc_sample_and_transmit_fast_path(uint16_t *sample_data_out)
+{
+ bool send_header = false;
+ // 1. Start all ADC conversions.
+ SET_PIN_CONVST12_HIGH;
+ SET_PIN_CONVST34_HIGH;
+ SET_PIN_CONVST56_HIGH;
+ SET_PIN_CONVST78_HIGH;
+
+ //Timing optimization: do work before the wait state below.
+
+ uint32_t start_cycles = DWT->CYCCNT;
+ // reset DMA routing state machine
+ try_reset_routing_state();
+
+ // Calculate 1.3 microseconds in CPU cycles (integer math safe)
+ uint32_t wait_cycles = (SystemCoreClock / 1000000) * 13 / 10;
+
+ // Deterministic wait for exactly 1300ns using hardware cycles, not NOPs
+ while ((DWT->CYCCNT - start_cycles) < wait_cycles) {
+ // Spin perfectly safely
+ }
+
+ // 2. Start the SCLKs
+ drv_spi_start_read_two_16bits(SPI1);
+ drv_spi_start_read_two_16bits(SPI4);
+ drv_spi_start_read_two_16bits(SPI5);
+ drv_spi_start_read_two_16bits(SPI6);
+
+ // Timing optimization: send our first header bytes here because code after this is waiting
+ drv_uart_putc_fast(USART2, 0x90);
+ drv_uart_putc_fast(USART3, 0x90);
+
+ // 3. Wait and read first ADC data (Channels 0, 1, 2, 3)
+ drv_spi_finish_read_one_16bits(SPI1, &sample_data_out[3]);
+ drv_spi_finish_read_one_16bits(SPI4, &sample_data_out[1]);
+ drv_spi_finish_read_one_16bits(SPI5, &sample_data_out[0]);
+ drv_spi_finish_read_one_16bits(SPI6, &sample_data_out[2]);
+
+ //Timing optimization: wait for only the last SPI that we started
+ drv_spi_wait_for_RX(SPI6);
+
+ // Read second ADC data (Channels 4, 5, 6, 7)
+ drv_spi_get_DR(SPI1, &sample_data_out[7]);
+ drv_spi_get_DR(SPI4, &sample_data_out[5]);
+ drv_spi_get_DR(SPI5, &sample_data_out[4]);
+ drv_spi_get_DR(SPI6, &sample_data_out[6]);
+
+ for (uint32_t i = 0; i < 4; i++) {
+ //don't send first header because we sent it earlier (timing optimization)
+ if (send_header){
+ drv_uart_putc_fast(USART2, 0x90 | i);
+ drv_uart_putc_fast(USART3, 0x90 | i);
+ }
+ else {
+ send_header = true;
+ }
+
+ drv_uart_putc_fast(USART3, (uint8_t)(sample_data_out[i + 4] >> 8));
+ drv_uart_putc_fast(USART2, (uint8_t)(sample_data_out[i] >> 8));
+
+ drv_uart_putc_fast(USART2, (uint8_t)sample_data_out[i]);
+ drv_uart_putc_fast(USART3, (uint8_t)sample_data_out[i + 4]);
+ }
+
+ // End conversion
+ SET_PIN_CONVST12_LOW;
+ SET_PIN_CONVST34_LOW;
+ SET_PIN_CONVST56_LOW;
+ SET_PIN_CONVST78_LOW;
+}
+
+// This ISR is triggered by the AMDC to sync the ADC
+// conversions to the AMDC PWM carrier waveform. In
+// this ISR, all the mainboard ADCs should be sampled.
+void EXTI3_IRQHandler(void)
+{
+ // alert daisy chained AMDSs to begin converting
+ GPIO_TOGGLE_PIN(GPIOD, GPIO_PIN_1);
+
+#ifdef BENCHMARK_MODE
+ // =========================================================================
+ // INJECT MOCK DMA DATA FOR BENCHMARKING
+ // Simulates 8 packets (24 bytes) arriving instantly on the SYNC edge.
+ // =========================================================================
+ try_reset_routing_state();
+ uint8_t current_head = mock_dma_write_head;
+ for (int i = 0; i < 24; i++) {
+ uint8_t idx = (uint8_t)(current_head + i);
+ if (i % 3 == 0) {
+ DAISY_RX1_Pool[idx] = 0x90; // Valid Header
+ DAISY_RX2_Pool[idx] = 0x90;
+ } else {
+ DAISY_RX1_Pool[idx] = 0xAA; // Dummy Payload Data
+ DAISY_RX2_Pool[idx] = 0xBB;
+ }
+ }
+ // Instantly advance the mock hardware write head
+ mock_dma_write_head = (uint8_t)(current_head + 24);
+#endif
+
+ uint16_t new_data[8] = { 0 };
+
+ // =========================================================================
+ // FAST PATH: Integrated Sampling and Transmission!
+ // =========================================================================
+ if (active_sensor_mask == 0xFF) {
+ adc_sample_and_transmit_fast_path(new_data);
+ }
+ // =========================================================================
+ // SLOW PATH: Legacy sampling for Partial Masks
+ // =========================================================================
+ else {
+#ifndef BENCHMARK_MODE
+ try_reset_routing_state();
+#endif
+ adc_sample_all_daughtercards(new_data);
+
+ for (uint32_t i = 0; i < 4; i++) {
+ uint8_t header = 0x90 | i;
+
+ if ((active_sensor_mask & (1 << i)) && (active_sensor_mask & (1 << (i + 4)))) {
+ drv_uart_putc_fast(USART2, header);
+ drv_uart_putc_fast(USART3, header);
+ drv_uart_putc_fast(USART2, (uint8_t)(new_data[i] >> 8));
+ drv_uart_putc_fast(USART3, (uint8_t)(new_data[i + 4] >> 8));
+ drv_uart_putc_fast(USART2, (uint8_t)(new_data[i]));
+ drv_uart_putc_fast(USART3, (uint8_t)(new_data[i + 4]));
+ } else {
+ bool u3 = false;
+ bool u2 = false;
+
+ if (active_sensor_mask & (1 << i)) {
+ drv_uart_putc_fast(USART2, header);
+ u2 = true;
+ drv_uart_putc_fast(USART2, (uint8_t)(new_data[i] >> 8));
+ }
+ if (active_sensor_mask & (1 << (i + 4))) {
+ drv_uart_putc_fast(USART3, header);
+ u3 = true;
+ drv_uart_putc_fast(USART3, (uint8_t)(new_data[i + 4] >> 8));
+ }
+ if (u2) drv_uart_putc_fast(USART2, (uint8_t)(new_data[i] & 0xFF));
+ if (u3) drv_uart_putc_fast(USART3, (uint8_t)(new_data[i + 4] & 0xFF));
+ }
+ }
+ }
+
+ // Handle any DMA data that has been received from daisy chain
+ try_process_routing();
+
+ NVIC_ClearPendingIRQ(EXTI3_IRQn);
+ __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_3);
+ NVIC_ClearPendingIRQ(EXTI3_IRQn);
+}
+
+#elif defined(TARGET_2S)
+
+static void adc_sample_1_5_daughtercards(uint16_t *sample_data_out)
+{
+ // This function has been optimized for very
+ // fast operation of SPI5 interface
+ // to cards 1 and 5.
+ //
+ // It directly manipulates the SPI peripherals'
+ // registers to read in data from the ADCs. The ordering
+ // of operations may look strange, but this is to minimize
+ // wait time of the various APB interconnects in the MCU.
+ //
+ // The ADC devices support a max of 400ksps. Looking at
+ // the waveforms from this function, the CONVST line is
+ // asserted for effectively 280kHz... It could be faster,
+ // but its not terrible...
+
+ // Start all ADC conversions.
+ // ADC conversion triggered by CONVST56 connects to SPI5
+ SET_PIN_CONVST56_HIGH;
+
+ // Wait for ADC conversion to complete (per datasheet, >= 1300ns
+ // Each NOP takes 5ns, unrolled so branches don't affect timing...
+ //
+ // We need 260 NOPs
+ NOP256;
+ NOP4;
+
+ // Smartly read all data from ADC.
+ // This starts the SPI peripheral,then waits for it to
+ // complete and gets the resulting data.
+
+ // Start the SCLKs
+ drv_spi_start_read_two_16bits(SPI5);
+
+ // Wait and read first ADC data
+ drv_spi_finish_read_one_16bits(SPI5, &sample_data_out[0]);
+
+ // Wait for second ADC data to complete
+ drv_spi_wait_for_RX(SPI5);
+
+ // End conversion
+ SET_PIN_CONVST56_LOW;
+
+ // Read second ADC data
+ drv_spi_get_DR(SPI5, &sample_data_out[4]);
+}
+
+void adc_sample_and_transmit_1_5_fast_path(uint16_t *sample_data_out)
+{
+ // 1. Start all ADC conversions.
+ SET_PIN_CONVST56_HIGH;
+
+ //Timing optimization: do work before the wait state below.
+
+ uint32_t start_cycles = DWT->CYCCNT;
+ // reset DMA routing state machine
+ try_reset_routing_state();
+
+ // Calculate 1.3 microseconds in CPU cycles (integer math safe)
+ uint32_t wait_cycles = (SystemCoreClock / 1000000) * 13 / 10;
+
+ // Deterministic wait for exactly 1300ns using hardware cycles, not NOPs
+ while ((DWT->CYCCNT - start_cycles) < wait_cycles) {
+ // Spin perfectly safely
+ }
+
+ // 2. Start the SCLK
+ drv_spi_start_read_two_16bits(SPI5);
+
+ // 3. Wait and read first ADC data (Channels 0, 1, 2, 3)
+ drv_spi_finish_read_one_16bits(SPI5, &sample_data_out[0]);
+
+ //Timing optimization: wait for only the last SPI that we started
+ drv_spi_wait_for_RX(SPI5);
+
+ drv_uart_putc_fast(USART2, 0x90);
+ drv_uart_putc_fast(USART3, 0x90);
+
+ // Read second ADC data (Channels 4, 5, 6, 7)
+ drv_spi_get_DR(SPI5, &sample_data_out[4]);
+
+ // don't send first header
+ drv_uart_putc_fast(USART2, (uint8_t)(sample_data_out[0] >> 8));
+ drv_uart_putc_fast(USART3, (uint8_t)(sample_data_out[4] >> 8));
+
+ drv_uart_putc_fast(USART2, (uint8_t)sample_data_out[0]);
+ drv_uart_putc_fast(USART3, (uint8_t)sample_data_out[4]);
+
+ // End conversion
+ SET_PIN_CONVST56_LOW;
+}
+
+// This ISR is for the FBC and is triggered by the
+// AMDC to sync the ADCconversions to the AMDC PWM
+// carrier waveform. In this ISR, on 2 ADCs should be sampled.
+//void EXTI15_10_IRQHandler(void)
+void EXTI15_10_IRQHandler(void)
+{
+ // alert daisy chained AMDSs to begin converting
+ GPIO_TOGGLE_PIN(GPIOG, GPIO_PIN_14);
+
+#ifdef BENCHMARK_MODE
+ // =========================================================================
+ // INJECT MOCK DMA DATA FOR BENCHMARKING
+ // Simulates 8 packets (24 bytes) arriving instantly on the SYNC edge.
+ // =========================================================================
+ try_reset_routing_state();
+ uint8_t current_head = mock_dma_write_head;
+ for (int i = 0; i < 3; i++) {
+ uint8_t idx = (uint8_t)(current_head + i);
+ if (i == 0) {
+ DAISY_RX1_Pool[idx] = 0x90; // Valid Header
+ DAISY_RX2_Pool[idx] = 0x90;
+ } else if (i == 3) {
+ DAISY_RX1_Pool[idx] = 0x94; // Valid Header
+ DAISY_RX2_Pool[idx] = 0x94;
+ } else {
+ DAISY_RX1_Pool[idx] = 0xAA; // Dummy Payload Data
+ DAISY_RX2_Pool[idx] = 0xBB;
+ }
+ }
+ // Instantly advance the mock hardware write head
+ mock_dma_write_head = (uint8_t)(current_head + 3);
+#endif
+
+ uint16_t new_data[8] = { 0 };
+
+ // =========================================================================
+ // FAST PATH: Integrated Sampling and Transmission!
+ // =========================================================================
+ if (active_sensor_mask == 0x11) {
+ adc_sample_and_transmit_1_5_fast_path(new_data);
+ }
+ // =========================================================================
+ // SLOW PATH: Safe loop for Partial Masks
+ // =========================================================================
+ else {
+#ifndef BENCHMARK_MODE
+ try_reset_routing_state();
+#endif
+ adc_sample_1_5_daughtercards(new_data);
+
+ bool u3 = false;
+ bool u2 = false;
+ uint8_t header = 0x90;
+
+ if (active_sensor_mask & (1 << 0)) {
+ drv_uart_putc_fast(USART2, header);
+ u2 = true;
+ drv_uart_putc_fast(USART2, (uint8_t)(new_data[0] >> 8));
+ }
+ if (active_sensor_mask & (1 << 4)) {
+ drv_uart_putc_fast(USART3, header);
+ u3 = true;
+ drv_uart_putc_fast(USART3, (uint8_t)(new_data[4] >> 8));
+ }
+ if (u2) drv_uart_putc_fast(USART2, (uint8_t)(new_data[0]));
+ if (u3) drv_uart_putc_fast(USART3, (uint8_t)(new_data[4]));
+ }
+
+ uint32_t start_cycles = DWT->CYCCNT;
+
+ // Calculate 1 microseconds in CPU cycles (integer math safe)
+ uint32_t wait_cycles = (SystemCoreClock / 1000000);
+
+
+ while (!(USART2->ISR & UART_FLAG_TC) && !(USART3->ISR & UART_FLAG_TC) && ((DWT->CYCCNT - start_cycles) < wait_cycles)) {
+
+ }
+
+ //Handle any DMA data that has been received from daisy chain
+ try_process_routing(); // This try function is thread safe
+
+ // Clear all pending IRQs for ADC conversions at the
+ // end of this ISR so that the system realigns the
+ // ADC conversions with the SYNC signal from the AMDC.
+ //
+ // For some reason, this only works if we call both of these:
+ NVIC_ClearPendingIRQ(EXTI15_10_IRQn);
+ __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_11);
+ NVIC_ClearPendingIRQ(EXTI15_10_IRQn);
+}
+#else
+#error "Please define a target board (TARGET_AMDS or TARGET_2S)!"
+#endif
+
+static void setup_pin_CONVST(void)
+{
+ GPIO_InitTypeDef GPIO_InitStruct = { 0 };
+
+ __HAL_RCC_GPIOE_CLK_ENABLE();
+ __HAL_RCC_GPIOF_CLK_ENABLE();
+ __HAL_RCC_GPIOG_CLK_ENABLE();
+
+ // Configure GPIO pin Output Level
+ HAL_GPIO_WritePin(GPIOE, GPIO_PIN_10 | GPIO_PIN_11, GPIO_PIN_RESET);
+ HAL_GPIO_WritePin(GPIOF, GPIO_PIN_6, GPIO_PIN_RESET);
+ HAL_GPIO_WritePin(GPIOG, GPIO_PIN_8, GPIO_PIN_RESET);
+
+ // Configure GPIO pins
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+
+ GPIO_InitStruct.Pin = GPIO_PIN_10 | GPIO_PIN_11;
+ HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
+
+ GPIO_InitStruct.Pin = GPIO_PIN_6;
+ HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
+
+ GPIO_InitStruct.Pin = GPIO_PIN_8;
+ HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
+}
+
+static void setup_pin_SYNC_ADC(void)
+{
+ // ADC Sync is a square wave input where every edge should
+ // trigger a sampling event from the mainboard ADCs.
+ //
+ // These edges are aligned to the PWM carrier on the AMDC.
+
+ GPIO_InitTypeDef GPIO_InitStruct = { 0 };
+
+#if defined(TARGET_AMDS)
+ __HAL_RCC_GPIOA_CLK_ENABLE();
+ __HAL_RCC_GPIOD_CLK_ENABLE();
+
+ // Configure GPIO pin Output Level
+ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);
+ HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1, GPIO_PIN_SET);
+
+ // Configure GPIO pins
+ GPIO_InitStruct.Pin = GPIO_PIN_3;
+ GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+ GPIO_InitStruct.Pin = GPIO_PIN_1;
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
+
+ // EXTI interrupt init
+ HAL_NVIC_SetPriority(EXTI3_IRQn, 10, 0);
+ HAL_NVIC_EnableIRQ(EXTI3_IRQn);
+#elif defined(TARGET_2S)
+ __HAL_RCC_GPIOB_CLK_ENABLE();
+ __HAL_RCC_GPIOG_CLK_ENABLE();
+
+ // Configure GPIO pin Output Level
+ HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET);
+ HAL_GPIO_WritePin(GPIOG, GPIO_PIN_14, GPIO_PIN_SET);
+
+ // Configure GPIO pins
+ GPIO_InitStruct.Pin = GPIO_PIN_11;
+ GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+
+ GPIO_InitStruct.Pin = GPIO_PIN_14;
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
+
+ // EXTI interrupt init
+ HAL_NVIC_SetPriority(EXTI15_10_IRQn, 10, 0);
+ HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
+#else
+ #error "Please define a target board (TARGET_AMDS or TARGET_2S)!"
+#endif
+}
diff --git a/Mainboard/Firmware/motherboard_v1/Core/Src/drv_clock.c b/Mainboard/Firmware/mainboard/Core/Src/drv_clock.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Core/Src/drv_clock.c
rename to Mainboard/Firmware/mainboard/Core/Src/drv_clock.c
diff --git a/Mainboard/Firmware/motherboard_v1/Core/Src/drv_gpio.c b/Mainboard/Firmware/mainboard/Core/Src/drv_gpio.c
similarity index 96%
rename from Mainboard/Firmware/motherboard_v1/Core/Src/drv_gpio.c
rename to Mainboard/Firmware/mainboard/Core/Src/drv_gpio.c
index 6f861e6e..6e1ab95f 100644
--- a/Mainboard/Firmware/motherboard_v1/Core/Src/drv_gpio.c
+++ b/Mainboard/Firmware/mainboard/Core/Src/drv_gpio.c
@@ -34,7 +34,7 @@ static void MX_GPIO_Init(void)
// Configure GPIO pin Output Level
HAL_GPIO_WritePin(GPIOD,
- GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2
+ GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11
| GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7,
GPIO_PIN_RESET);
@@ -78,9 +78,9 @@ static void MX_GPIO_Init(void)
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
// Configure GPIO pins : PD8 PD9 PD10 PD11
- // PD0 PD1 PD2 PD3
+ // PD3
// PD4 PD5 PD6 PD7
- GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2
+ GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11
| GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
diff --git a/Mainboard/Firmware/motherboard_v1/Core/Src/drv_i2c.c b/Mainboard/Firmware/mainboard/Core/Src/drv_i2c.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Core/Src/drv_i2c.c
rename to Mainboard/Firmware/mainboard/Core/Src/drv_i2c.c
diff --git a/Mainboard/Firmware/motherboard_v1/Core/Src/drv_led.c b/Mainboard/Firmware/mainboard/Core/Src/drv_led.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Core/Src/drv_led.c
rename to Mainboard/Firmware/mainboard/Core/Src/drv_led.c
diff --git a/Mainboard/Firmware/motherboard_v1/Core/Src/drv_spi.c b/Mainboard/Firmware/mainboard/Core/Src/drv_spi.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Core/Src/drv_spi.c
rename to Mainboard/Firmware/mainboard/Core/Src/drv_spi.c
diff --git a/Mainboard/Firmware/mainboard/Core/Src/drv_uart.c b/Mainboard/Firmware/mainboard/Core/Src/drv_uart.c
new file mode 100644
index 00000000..2867915a
--- /dev/null
+++ b/Mainboard/Firmware/mainboard/Core/Src/drv_uart.c
@@ -0,0 +1,750 @@
+#include "drv_uart.h"
+#include "defines.h"
+#include "drv_clock.h"
+#include "platform.h"
+#include
+
+static void MX_USART_UART_Init(UART_HandleTypeDef *huart, USART_TypeDef *handle);
+
+UART_HandleTypeDef huart2;
+UART_HandleTypeDef huart3;
+
+DMA_HandleTypeDef hdma_uart4_rx;
+DMA_HandleTypeDef hdma_uart5_rx;
+
+DMA_HandleTypeDef hdma_uart6_rx;
+DMA_HandleTypeDef hdma_uart1_rx;
+
+// Daisy Chain RX Peripherals
+UART_HandleTypeDef DAISY_RX1_UART;
+UART_HandleTypeDef DAISY_RX2_UART;
+
+uart_rx_tracker_t tracker1;
+uart_rx_tracker_t tracker2;
+uint8_t DAISY_RX1_Pool[AMDS_RX_BUF_SIZE];
+uint8_t DAISY_RX2_Pool[AMDS_RX_BUF_SIZE];
+
+// Global flag to track if routing is actively occurring.
+// Must be volatile so the compiler knows it can change inside an IRQ.
+volatile bool is_routing_active = false;
+
+#ifdef BENCHMARK_MODE
+ volatile uint8_t mock_dma_write_head = 0;
+ #define GET_W1() mock_dma_write_head
+ #define GET_W2() mock_dma_write_head
+#else
+ // NDTR counts down, so the write head is (SIZE - NDTR).
+ // Casting to uint8_t naturally handles the modulo wrap-around at 256.
+ // AMDS_RX_BUF_SIZE MUST BE 256
+ #define GET_W1() (uint8_t)(AMDS_RX_BUF_SIZE - __HAL_DMA_GET_COUNTER(DAISY_RX1_UART.hdmarx))
+ #define GET_W2() (uint8_t)(AMDS_RX_BUF_SIZE - __HAL_DMA_GET_COUNTER(DAISY_RX2_UART.hdmarx))
+#endif
+
+bool drv_uart_has_dma_data(void) {
+ // Reading these 8-bit values is natively atomic, so it is safe to
+ // evaluate them even if an interrupt is modifying them in the background.
+ uint8_t w1 = GET_W1();
+ uint8_t w2 = GET_W2();
+
+ return (tracker1.read_index != w1) || (tracker2.read_index != w2);
+}
+
+void process_routing(void) {
+ // Load tracking state into local CPU registers
+ uint8_t r1 = tracker1.read_index;
+ uint8_t r2 = tracker2.read_index;
+ uint8_t s1 = tracker1.state;
+ uint8_t s2 = tracker2.state;
+
+ uint8_t w1 = GET_W1();
+ uint8_t w2 = GET_W2();
+
+ // Process as long as either buffer has data
+ while ((r1 != w1) || (r2 != w2)) {
+ // Calculate how many bytes are sitting unread in the DMA buffer
+ // Because everything is cast to uint8_t, this math safely handles
+ // circular buffer wrap-around natively (e.g. w4=2, r4=254 -> avail=4)
+ uint8_t avail1 = (uint8_t)(w1 - r1);
+ uint8_t avail2 = (uint8_t)(w2 - r2);
+
+
+ if (avail1 < 3 || avail2 < 3) {
+ // 1.3us timeout to let us receive enough data for dual-stream fast path
+ uint32_t start_cycles = DWT->CYCCNT;
+
+ // Calculate 1.3 microseconds in CPU cycles (integer math safe)
+ uint32_t wait_cycles = (SystemCoreClock / 1000000) * 13 / 10;
+
+ while ((avail1 >= 0 && avail1 <= 2) || (avail2 >= 0 && avail2 <= 2)) {
+ w1 = GET_W1();
+ w2 = GET_W2();
+
+ avail1 = (uint8_t)(w1 - r1);
+ avail2 = (uint8_t)(w2 - r2);
+
+ // Break if we reach the 2us timeout
+ if ((DWT->CYCCNT - start_cycles) > wait_cycles) {
+ break;
+ }
+ }
+ }
+
+ // =====================================================================
+ // OPTIMIZATION 1: DUAL-STREAM FAST PATH (Perfect Interleaving)
+ // =====================================================================
+ // If both streams have at least a full 3-byte packet, process them completely
+ // interleaved to keep both hardware lines saturated simultaneously.
+ while ((s1 == STATE_IDLE && avail1 >= 3) && (s2 == STATE_IDLE && avail2 >= 3)) {
+ uint8_t h1 = DAISY_RX1_Pool[r1];
+ uint8_t h2 = DAISY_RX2_Pool[r2];
+
+ if (((h1 & 0xF0) == 0x90) && ((h2 & 0xF0) == 0x90)) {
+ // Byte 1: Headers (Incremented)
+ drv_uart_putc_fast(USART2, h1 + 4);
+ drv_uart_putc_fast(USART3, h2 + 4);
+
+ // Byte 2: MSB
+ drv_uart_putc_fast(USART3, DAISY_RX2_Pool[(uint8_t)(r2 + 1)]);
+ drv_uart_putc_fast(USART2, DAISY_RX1_Pool[(uint8_t)(r1 + 1)]);
+
+ // Byte 3: LSB
+ drv_uart_putc_fast(USART2, DAISY_RX1_Pool[(uint8_t)(r1 + 2)]);
+ drv_uart_putc_fast(USART3, DAISY_RX2_Pool[(uint8_t)(r2 + 2)]);
+
+ r1 += 3;
+ r2 += 3;
+ avail1 -= 3;
+ avail2 -= 3;
+
+ if (avail1 < 3 || avail2 < 3) {
+ uint32_t start_cycles = DWT->CYCCNT;
+
+ // Calculate 3 microseconds in CPU cycles (integer math safe)
+ uint32_t wait_cycles = (SystemCoreClock / 1000000) * 3;
+
+ while ((avail1 >= 0 && avail1 <= 2) || (avail2 >= 0 && avail2 <= 2)) {
+ w1 = GET_W1();
+ w2 = GET_W2();
+
+ avail1 = (uint8_t)(w1 - r1);
+ avail2 = (uint8_t)(w2 - r2);
+
+ // Break if we reach the 3us timeout
+ if ((DWT->CYCCNT - start_cycles) > wait_cycles) {
+ break;
+ }
+ }
+ }
+ } else {
+ break; // Misaligned or corrupted header, break to let the slow-path handle it
+ }
+ }
+
+ // =====================================================================
+ // OPTIMIZATION 2: SINGLE-STREAM FAST PATHS
+ // =====================================================================
+ // If one UART receives data slightly faster than the other, process it.
+ while (s1 == STATE_IDLE && avail1 >= 3) {
+ uint8_t h1 = DAISY_RX1_Pool[r1];
+ if ((h1 & 0xF0) == 0x90) {
+ drv_uart_putc_fast(USART2, h1 + 4);
+ drv_uart_putc_fast(USART2, DAISY_RX1_Pool[(uint8_t)(r1 + 1)]);
+ drv_uart_putc_fast(USART2, DAISY_RX1_Pool[(uint8_t)(r1 + 2)]);
+
+ r1 += 3;
+ avail1 -= 3;
+ } else {
+ break;
+ }
+ }
+
+ while (s2 == STATE_IDLE && avail2 >= 3) {
+ uint8_t h2 = DAISY_RX2_Pool[r2];
+ if ((h2 & 0xF0) == 0x90) {
+ drv_uart_putc_fast(USART3, h2 + 4);
+ drv_uart_putc_fast(USART3, DAISY_RX2_Pool[(uint8_t)(r2 + 1)]);
+ drv_uart_putc_fast(USART3, DAISY_RX2_Pool[(uint8_t)(r2 + 2)]);
+
+ r2 += 3;
+ avail2 -= 3;
+ } else {
+ break;
+ }
+ }
+
+ // =====================================================================
+ // SLOW PATH: Fragmentation / State Recovery
+ // =====================================================================
+ // We only fall down here if a packet is fragmented across a DMA update
+ // boundary or if data is corrupted. We can safely revert to the simple
+ // 1-byte-at-a-time logic.
+ while (r1 != w1 && s1 != STATE_IDLE) {
+ uint8_t b1 = DAISY_RX1_Pool[r1++];
+ if (s1 == STATE_GOT_HEADER) {
+ drv_uart_putc_fast(USART2, b1);
+ s1 = STATE_GOT_MSB;
+ } else { // STATE_GOT_MSB
+ drv_uart_putc_fast(USART2, b1);
+ s1 = STATE_IDLE;
+ }
+ }
+
+ while (r2 != w2 && s2 != STATE_IDLE) {
+ uint8_t b2 = DAISY_RX2_Pool[r2++];
+ if (s2 == STATE_GOT_HEADER) {
+ drv_uart_putc_fast(USART3, b2);
+ s2 = STATE_GOT_MSB;
+ } else { // STATE_GOT_MSB
+ drv_uart_putc_fast(USART3, b2);
+ s2 = STATE_IDLE;
+ }
+ }
+
+ // Check if we caught up to our cached write pointers.
+ // If so, re-sample the DMA registers to see if new data arrived
+ // while we were actively processing the previous bytes.
+ if ((r1 == w1) && (r2 == w2)) {
+ w1 = GET_W1();
+ w2 = GET_W2();
+ }
+ }
+
+ // Store states back
+ tracker1.read_index = r1;
+ tracker2.read_index = r2;
+ tracker1.state = s1;
+ tracker2.state = s2;
+}
+
+#if defined(TARGET_AMDS)
+void UART4_IRQHandler(void)
+{
+ // Check for Parity, Overrun, Noise, or Frame errors
+ if (__HAL_UART_GET_FLAG(&DAISY_RX1_UART, UART_FLAG_PE) ||
+ __HAL_UART_GET_FLAG(&DAISY_RX1_UART, UART_FLAG_ORE) ||
+ __HAL_UART_GET_FLAG(&DAISY_RX1_UART, UART_FLAG_NE) ||
+ __HAL_UART_GET_FLAG(&DAISY_RX1_UART, UART_FLAG_FE))
+ {
+ // 1. Clear the error flags (Added UART_CLEAR_PEF)
+ __HAL_UART_CLEAR_IT(&DAISY_RX1_UART, UART_CLEAR_PEF | UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_FEF);
+
+ // 2. IMPORTANT: Re-enable DMA receiver request
+ // The hardware/HAL drops this bit on error, halting the DMA stream.
+ SET_BIT(DAISY_RX1_UART.Instance->CR3, USART_CR3_DMAR);
+
+ return;
+ }
+
+ // Process normal RX/TX interrupts via the HAL
+ HAL_UART_IRQHandler(&DAISY_RX1_UART);
+}
+
+void DMA1_Stream2_IRQHandler(void)
+{
+ HAL_DMA_IRQHandler(&hdma_uart4_rx);
+}
+
+void UART5_IRQHandler(void)
+{
+ // Check for Overrun, Noise, or Frame errors
+ if (__HAL_UART_GET_FLAG(&DAISY_RX2_UART, UART_FLAG_PE) ||
+ __HAL_UART_GET_FLAG(&DAISY_RX2_UART, UART_FLAG_ORE) ||
+ __HAL_UART_GET_FLAG(&DAISY_RX2_UART, UART_FLAG_NE) ||
+ __HAL_UART_GET_FLAG(&DAISY_RX2_UART, UART_FLAG_FE))
+ {
+ // 1. Clear the error flags
+ __HAL_UART_CLEAR_IT(&DAISY_RX2_UART, UART_CLEAR_PEF | UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_FEF);
+
+ // 2. IMPORTANT: Re-enable DMA receiver request
+ // Sometimes HAL disables this bit (DMAR) on error.
+ SET_BIT(DAISY_RX2_UART.Instance->CR3, USART_CR3_DMAR);
+
+ return;
+ }
+ HAL_UART_IRQHandler(&DAISY_RX2_UART);
+}
+
+void DMA1_Stream0_IRQHandler(void)
+{
+ HAL_DMA_IRQHandler(&hdma_uart5_rx);
+}
+#elif defined(TARGET_2S)
+void USART6_IRQHandler(void)
+{
+ // Check for Parity, Overrun, Noise, or Frame errors
+ if (__HAL_UART_GET_FLAG(&DAISY_RX1_UART, UART_FLAG_PE) ||
+ __HAL_UART_GET_FLAG(&DAISY_RX1_UART, UART_FLAG_ORE) ||
+ __HAL_UART_GET_FLAG(&DAISY_RX1_UART, UART_FLAG_NE) ||
+ __HAL_UART_GET_FLAG(&DAISY_RX1_UART, UART_FLAG_FE))
+ {
+
+ // 1. Clear the error flags
+ __HAL_UART_CLEAR_IT(&DAISY_RX1_UART, UART_CLEAR_PEF | UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_FEF);
+
+ // 2. IMPORTANT: Re-enable DMA receiver request
+ // The hardware/HAL drops this bit on error, halting the DMA stream.
+ SET_BIT(DAISY_RX1_UART.Instance->CR3, USART_CR3_DMAR);
+
+ return;
+ }
+
+ // Process normal RX/TX interrupts via the HAL
+ HAL_UART_IRQHandler(&DAISY_RX1_UART);
+}
+
+void DMA2_Stream2_IRQHandler(void)
+{
+ HAL_DMA_IRQHandler(&hdma_uart6_rx);
+}
+
+void USART1_IRQHandler(void)
+{
+ // Check for Overrun, Noise, or Frame errors
+ if (__HAL_UART_GET_FLAG(&DAISY_RX2_UART, UART_FLAG_PE) ||
+ __HAL_UART_GET_FLAG(&DAISY_RX2_UART, UART_FLAG_ORE) ||
+ __HAL_UART_GET_FLAG(&DAISY_RX2_UART, UART_FLAG_NE) ||
+ __HAL_UART_GET_FLAG(&DAISY_RX2_UART, UART_FLAG_FE))
+ {
+
+ // 1. Clear the error flags
+ __HAL_UART_CLEAR_IT(&DAISY_RX2_UART, UART_CLEAR_PEF | UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_FEF);
+
+ // 2. IMPORTANT: Re-enable DMA receiver request
+ // Sometimes HAL disables this bit (DMAR) on error.
+ SET_BIT(DAISY_RX2_UART.Instance->CR3, USART_CR3_DMAR);
+
+ return;
+ }
+ HAL_UART_IRQHandler(&DAISY_RX2_UART);
+}
+
+void DMA2_Stream5_IRQHandler(void)
+{
+ HAL_DMA_IRQHandler(&hdma_uart1_rx);
+}
+#else
+ #error "Please define a target board (TARGET_AMDS or TARGET_2S)!"
+#endif
+
+void USART2_IRQHandler(void) {
+ HAL_UART_IRQHandler(&huart2);
+}
+
+void USART3_IRQHandler(void) {
+ HAL_UART_IRQHandler(&huart3);
+}
+
+void drv_uart_init(void)
+{
+ // Twiddle some bits in the RCC module to set USART2 and USART3 clock source.
+ // By default, the source is PCLK1 (i.e. APB1 clock), but this is 4x slower than
+ // the system clock. We can configure the clock tree to use SYSCLK to get
+ // higher data throughput!
+ //
+ // This feature is not really documented that well... :(
+
+ __HAL_RCC_USART2_CONFIG(RCC_USART2CLKSOURCE_SYSCLK);
+ __HAL_RCC_USART3_CONFIG(RCC_USART3CLKSOURCE_SYSCLK);
+#if defined(TARGET_AMDS)
+ __HAL_RCC_UART4_CONFIG(RCC_UART4CLKSOURCE_SYSCLK);
+ __HAL_RCC_UART5_CONFIG(RCC_UART5CLKSOURCE_SYSCLK);
+#elif defined(TARGET_2S)
+ __HAL_RCC_USART6_CONFIG(RCC_USART6CLKSOURCE_SYSCLK);
+ __HAL_RCC_USART1_CONFIG(RCC_USART1CLKSOURCE_SYSCLK);
+#else
+ #error "Please define a target board (TARGET_AMDS or TARGET_2S)!"
+#endif
+
+ MX_USART_UART_Init(&huart2, USART2);
+ MX_USART_UART_Init(&huart3, USART3);
+
+#if defined(TARGET_AMDS)
+ MX_USART_UART_Init(&DAISY_RX1_UART, UART4);
+ MX_USART_UART_Init(&DAISY_RX2_UART, UART5);
+#elif defined(TARGET_2S)
+ MX_USART_UART_Init(&DAISY_RX1_UART, USART6);
+ MX_USART_UART_Init(&DAISY_RX2_UART, USART1);
+#else
+ #error "Please define a target board (TARGET_AMDS or TARGET_2S)!"
+#endif
+}
+
+static void MX_USART_UART_Init(UART_HandleTypeDef *huart, USART_TypeDef *handle)
+{
+ // Configure USART peripherals.
+ //
+ // Baud Rate: Each USART peripheral can be clocked from a variety of sources.
+ // During uart_init() function, we set the clock tree mux such that all uart peripherals
+ // are now clocked by the system clock, which is configured to
+ // 200 MHz via the PLL.
+ //
+ // If we configure our USART using oversampling of 8, we can get a baud
+ // rate of 200e6 / 10 = 20 Mbps
+ uint32_t max_baudrate = SYSCLK_FREQ_HZ / 10; // 20 Mbps
+
+ // Also, note that the AMDC FPGA is running at 200 MHz, so the fact that the
+ // baud rate is an integer multiple of the FPGA clock is actually very nice!
+ // This will make parsing data more robust on FPGA.
+
+ huart->Instance = handle;
+ huart->Init.BaudRate = max_baudrate;
+ huart->Init.WordLength = UART_WORDLENGTH_9B;
+ huart->Init.StopBits = UART_STOPBITS_2;
+ huart->Init.Parity = UART_PARITY_ODD;
+
+ if (huart->Instance == UART4 || huart->Instance == USART6) {
+ huart->Init.Mode = UART_MODE_RX;
+ } else if (huart->Instance == UART5 || huart->Instance == USART1) {
+ huart->Init.Mode = UART_MODE_RX;
+ } else {
+ huart->Init.Mode = UART_MODE_TX;
+ }
+
+ huart->Init.HwFlowCtl = UART_HWCONTROL_NONE;
+ huart->Init.OverSampling = UART_OVERSAMPLING_8;
+ huart->Init.OneBitSampling = UART_ONE_BIT_SAMPLE_ENABLE;
+ huart->AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
+
+ if (HAL_UART_Init(huart) != HAL_OK) {
+ PANIC;
+ }
+
+#if defined(TARGET_AMDS)
+ if (huart->Instance == UART4) {
+ NVIC_SetPriority(UART4_IRQn, 9);
+ HAL_NVIC_EnableIRQ(UART4_IRQn);
+
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF);
+ __HAL_UART_FLUSH_DRREGISTER(huart);
+
+ if (HAL_UART_Receive_DMA(&DAISY_RX1_UART, DAISY_RX1_Pool, AMDS_RX_BUF_SIZE) != HAL_OK) {
+ PANIC;
+ }
+ }
+
+ if (huart->Instance == UART5) {
+ NVIC_SetPriority(UART5_IRQn, 9);
+ HAL_NVIC_EnableIRQ(UART5_IRQn);
+
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF);
+ __HAL_UART_FLUSH_DRREGISTER(huart);
+
+ if (HAL_UART_Receive_DMA(&DAISY_RX2_UART, DAISY_RX2_Pool, AMDS_RX_BUF_SIZE) != HAL_OK) {
+ PANIC;
+ }
+ }
+#elif defined(TARGET_2S)
+ if (huart->Instance == USART6) {
+ NVIC_SetPriority(USART6_IRQn, 9);
+ HAL_NVIC_EnableIRQ(USART6_IRQn);
+
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF);
+ __HAL_UART_FLUSH_DRREGISTER(huart);
+
+ if (HAL_UART_Receive_DMA(&DAISY_RX1_UART, DAISY_RX1_Pool, AMDS_RX_BUF_SIZE) != HAL_OK) {
+ PANIC;
+ }
+ } else if (huart->Instance == USART1) {
+ NVIC_SetPriority(USART1_IRQn, 9);
+ HAL_NVIC_EnableIRQ(USART1_IRQn);
+
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF);
+ __HAL_UART_FLUSH_DRREGISTER(huart);
+
+ if (HAL_UART_Receive_DMA(&DAISY_RX2_UART, DAISY_RX2_Pool, AMDS_RX_BUF_SIZE) != HAL_OK) {
+ PANIC;
+ }
+ }
+#else
+ #error "Please define a target board (TARGET_AMDS or TARGET_2S)!"
+#endif
+ if (huart->Instance == USART2) {
+ NVIC_SetPriority(USART2_IRQn, 10);
+ HAL_NVIC_EnableIRQ(USART2_IRQn);
+
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF);
+ __HAL_UART_FLUSH_DRREGISTER(huart);
+
+ } else if (huart->Instance == USART3) {
+ NVIC_SetPriority(USART3_IRQn, 10);
+ HAL_NVIC_EnableIRQ(USART3_IRQn);
+
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF);
+ __HAL_UART_FLUSH_DRREGISTER(huart);
+
+ }
+}
+
+void HAL_UART_MspInit(UART_HandleTypeDef *uartHandle)
+{
+
+ GPIO_InitTypeDef GPIO_InitStruct = { 0 };
+
+ if (uartHandle->Instance == USART2) {
+ // USART2 clock enable
+ __HAL_RCC_USART2_CLK_ENABLE();
+
+ __HAL_RCC_GPIOA_CLK_ENABLE();
+ // USART2 GPIO Configuration
+ // PA2 ------> USART2_TX
+ // PA3 ------> USART2_RX
+ GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+ }
+
+ else if (uartHandle->Instance == USART3) {
+ // USART3 clock enable
+ __HAL_RCC_USART3_CLK_ENABLE();
+
+ __HAL_RCC_GPIOB_CLK_ENABLE();
+ // USART3 GPIO Configuration
+ // PB10 ------> USART3_TX
+ // PB11 ------> USART3_RX
+ GPIO_InitStruct.Pin = GPIO_PIN_10 | GPIO_PIN_11;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
+ HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+ }
+#if defined(TARGET_AMDS)
+ else if (uartHandle->Instance == UART4) {
+ // USART3 clock enable
+ __HAL_RCC_UART4_CLK_ENABLE();
+ __HAL_RCC_DMA1_CLK_ENABLE();
+
+ __HAL_RCC_GPIOD_CLK_ENABLE();
+ // USART3 GPIO Configuration
+ // PD0 ------> UART4_RX
+ // PD1 ------> UART4_TX
+ GPIO_InitStruct.Pin = GPIO_PIN_0;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
+ HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
+
+ // DMA config - check your device's DMA request mapping table
+ // for the correct stream/channel for UART4_RX
+ hdma_uart4_rx.Instance = DMA1_Stream2; // verify in datasheet
+ hdma_uart4_rx.Init.Channel = DMA_CHANNEL_4; // HAL constant for your device
+ hdma_uart4_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
+ hdma_uart4_rx.Init.PeriphInc = DMA_PINC_DISABLE; // RDR address stays fixed
+ hdma_uart4_rx.Init.MemInc = DMA_MINC_ENABLE; // buffer pointer increments
+ hdma_uart4_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
+ hdma_uart4_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
+ hdma_uart4_rx.Init.Mode = DMA_CIRCULAR; // or DMA_CIRCULAR (see note below)
+ hdma_uart4_rx.Init.Priority = DMA_PRIORITY_HIGH;
+ hdma_uart4_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
+
+ if (HAL_DMA_Init(&hdma_uart4_rx) != HAL_OK) {
+ PANIC;
+ }
+
+ // This links the DMA handle to the UART handle
+ __HAL_LINKDMA(uartHandle, hdmarx, hdma_uart4_rx);
+
+ // DMA stream IRQ
+ NVIC_SetPriority(DMA1_Stream2_IRQn, 6); // higher priority than UART
+ HAL_NVIC_EnableIRQ(DMA1_Stream2_IRQn);
+ }
+
+ else if (uartHandle->Instance == UART5) {
+ // USART3 clock enable
+ __HAL_RCC_UART5_CLK_ENABLE();
+ __HAL_RCC_DMA1_CLK_ENABLE();
+
+ __HAL_RCC_GPIOD_CLK_ENABLE();
+ // USART3 GPIO Configuration
+ // PD2 ------> UART5_RX
+ GPIO_InitStruct.Pin = GPIO_PIN_2;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ GPIO_InitStruct.Alternate = GPIO_AF8_UART5;
+ HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
+
+ // DMA config - check your device's DMA request mapping table
+ // for the correct stream/channel for UART5_RX
+ hdma_uart5_rx.Instance = DMA1_Stream0; // verify in datasheet
+ hdma_uart5_rx.Init.Channel = DMA_CHANNEL_4; // HAL constant for your device
+ hdma_uart5_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
+ hdma_uart5_rx.Init.PeriphInc = DMA_PINC_DISABLE; // RDR address stays fixed
+ hdma_uart5_rx.Init.MemInc = DMA_MINC_ENABLE; // buffer pointer increments
+ hdma_uart5_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
+ hdma_uart5_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
+ hdma_uart5_rx.Init.Mode = DMA_CIRCULAR; // or DMA_CIRCULAR (see note below)
+ hdma_uart5_rx.Init.Priority = DMA_PRIORITY_HIGH;
+ hdma_uart5_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
+
+ if (HAL_DMA_Init(&hdma_uart5_rx) != HAL_OK) {
+ PANIC;
+ }
+
+ // This links the DMA handle to the UART handle
+ __HAL_LINKDMA(uartHandle, hdmarx, hdma_uart5_rx);
+
+ // DMA stream IRQ
+ NVIC_SetPriority(DMA1_Stream0_IRQn, 6); // higher priority than UART
+ HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
+ }
+#elif defined(TARGET_2S)
+ else if (uartHandle->Instance == USART6) {
+ // USART6 clock enable
+ __HAL_RCC_USART6_CLK_ENABLE();
+ __HAL_RCC_DMA2_CLK_ENABLE();
+
+ __HAL_RCC_GPIOG_CLK_ENABLE();
+ // USART3 GPIO Configuration
+ // PG9 ------> UART4_RX
+ GPIO_InitStruct.Pin = GPIO_PIN_9;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ GPIO_InitStruct.Alternate = GPIO_AF8_USART6;
+ HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
+
+ // DMA config - check your device's DMA request mapping table
+ // for the correct stream/channel for USART6_RX pg 253 of reference manual
+ hdma_uart6_rx.Instance = DMA2_Stream2; // verify in reference manual
+ hdma_uart6_rx.Init.Channel = DMA_CHANNEL_5; // verify in reference manual
+ hdma_uart6_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
+ hdma_uart6_rx.Init.PeriphInc = DMA_PINC_DISABLE; // RDR address stays fixed
+ hdma_uart6_rx.Init.MemInc = DMA_MINC_ENABLE; // buffer pointer increments
+ hdma_uart6_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
+ hdma_uart6_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
+ hdma_uart6_rx.Init.Mode = DMA_CIRCULAR; // or DMA_CIRCULAR (see note below)
+ hdma_uart6_rx.Init.Priority = DMA_PRIORITY_HIGH;
+ hdma_uart6_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
+
+ if (HAL_DMA_Init(&hdma_uart6_rx) != HAL_OK) {
+ PANIC;
+ }
+
+ // This links the DMA handle to the UART handle
+ __HAL_LINKDMA(uartHandle, hdmarx, hdma_uart6_rx);
+
+ // DMA stream IRQ
+ NVIC_SetPriority(DMA2_Stream2_IRQn, 6); // higher priority than UART
+ HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
+ }
+
+ else if (uartHandle->Instance == USART1) {
+ // USART1 clock enable
+ __HAL_RCC_USART1_CLK_ENABLE();
+ __HAL_RCC_DMA2_CLK_ENABLE();
+
+ __HAL_RCC_GPIOA_CLK_ENABLE();
+ // USART1 GPIO Configuration
+ // PA10 ------> USART1_RX
+ GPIO_InitStruct.Pin = GPIO_PIN_10;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+ // DMA config - check your device's DMA request mapping table
+ // for the correct stream/channel for USART1_RX pg 253 of reference manual
+ hdma_uart1_rx.Instance = DMA2_Stream5; // verify in reference manual
+ hdma_uart1_rx.Init.Channel = DMA_CHANNEL_4; // verify in reference manual
+ hdma_uart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
+ hdma_uart1_rx.Init.PeriphInc = DMA_PINC_DISABLE; // RDR address stays fixed
+ hdma_uart1_rx.Init.MemInc = DMA_MINC_ENABLE; // buffer pointer increments
+ hdma_uart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
+ hdma_uart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
+ hdma_uart1_rx.Init.Mode = DMA_CIRCULAR; // or DMA_CIRCULAR (see note below)
+ hdma_uart1_rx.Init.Priority = DMA_PRIORITY_HIGH;
+ hdma_uart1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
+
+ if (HAL_DMA_Init(&hdma_uart1_rx) != HAL_OK) {
+ PANIC;
+ }
+
+ // This links the DMA handle to the UART handle
+ __HAL_LINKDMA(uartHandle, hdmarx, hdma_uart1_rx);
+
+ // DMA stream IRQ
+ NVIC_SetPriority(DMA2_Stream5_IRQn, 6); // higher priority than UART
+ HAL_NVIC_EnableIRQ(DMA2_Stream5_IRQn);
+ }
+#else
+ #error "Please define a target board (TARGET_AMDS or TARGET_2S)!"
+#endif
+}
+
+void HAL_UART_MspDeInit(UART_HandleTypeDef *uartHandle)
+{
+
+ if (uartHandle->Instance == USART2) {
+ /* Peripheral clock disable */
+ __HAL_RCC_USART2_CLK_DISABLE();
+
+ /**USART2 GPIO Configuration
+ PA2 ------> USART2_TX
+ PA3 ------> USART2_RX
+ */
+ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2 | GPIO_PIN_3);
+ }
+
+ else if (uartHandle->Instance == USART3) {
+ /* Peripheral clock disable */
+ __HAL_RCC_USART3_CLK_DISABLE();
+
+ /**USART3 GPIO Configuration
+ PB10 ------> USART3_TX
+ PB11 ------> USART3_RX
+ */
+ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10 | GPIO_PIN_11);
+ }
+#if defined(TARGET_AMDS)
+ else if (uartHandle->Instance == UART4) {
+ /* Peripheral clock disable */
+ __HAL_RCC_UART4_CLK_DISABLE();
+
+ /**USART3 GPIO Configuration
+ PD0 ------> UART4_RX
+ PD1 ------> UART4_TX
+ */
+ HAL_GPIO_DeInit(GPIOD, GPIO_PIN_0);
+ }
+
+ else if (uartHandle->Instance == UART5) {
+ /* Peripheral clock disable */
+ __HAL_RCC_UART5_CLK_DISABLE();
+
+ /**USART3 GPIO Configuration
+ PD2 ------> UART5_RX
+ */
+ HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2);
+ }
+#elif defined(TARGET_2S)
+ else if (uartHandle->Instance == USART6) {
+ /* Peripheral clock disable */
+ __HAL_RCC_USART6_CLK_DISABLE();
+
+ /**USART3 GPIO Configuration
+ PG9 ------> USART6_RX
+ PG14 ------> USART6_TX
+ */
+ HAL_GPIO_DeInit(GPIOG, GPIO_PIN_9 | GPIO_PIN_14);
+ }
+
+ else if (uartHandle->Instance == USART1) {
+ /* Peripheral clock disable */
+ __HAL_RCC_USART1_CLK_DISABLE();
+
+ /**USART3 GPIO Configuration
+ PA9 ------> UART5_TX
+ PA10 ------> UART5_RX
+ */
+ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9 | GPIO_PIN_10);
+ }
+#else
+ #error "Please define a target board (TARGET_AMDS or TARGET_2S)!"
+#endif
+}
diff --git a/Mainboard/Firmware/mainboard/Core/Src/main.c b/Mainboard/Firmware/mainboard/Core/Src/main.c
new file mode 100644
index 00000000..bdf6ac47
--- /dev/null
+++ b/Mainboard/Firmware/mainboard/Core/Src/main.c
@@ -0,0 +1,91 @@
+// Drivers
+#include "drv_clock.h"
+#include "drv_gpio.h"
+#include "drv_i2c.h"
+#include "drv_led.h"
+#include "drv_spi.h"
+#include "drv_uart.h"
+#include "platform.h"
+
+// Modules
+#include "adc.h"
+
+int main(void)
+{
+ // Reset of all peripherals, Initializes the Flash interface and the Systick
+ HAL_Init();
+
+ // Configure the system clock
+ drv_clock_init();
+
+ // Initialize peripherals
+ drv_spi_init();
+ drv_uart_init();
+ drv_led_init();
+
+ // Initialize the main modules
+ adc_init();
+
+ uint8_t led = 0;
+
+ // Use DWT cycle counter instead of HAL_GetTick()
+ uint32_t ledDelta = DWT->CYCCNT;
+
+ // Calculate how many CPU cycles are in 250ms.
+ uint32_t cyclesPer250ms = SystemCoreClock / 4;
+
+ // Disable the SysTick ISR
+ //
+ // The SysTick ISR causes jitter in the firmware operation,
+ // and since this project does not use the SysTick features,
+ // we do not need it to run during operation!
+ //
+ // Set bit 0 to 0
+ SysTick->CTRL &= 0xFFFFFFFE;
+
+ // Enable the Cortex-M7 DWT Cycle Counter for hardware delays
+ CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
+ DWT->LAR = 0xC5ACCE55;
+ DWT->CYCCNT = 0;
+ DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
+
+ // Infinite loop (all real work is done in ISRs)
+ while (1) {
+
+ // Handle DMA data from UARTs and route to correct destination.
+ // Only attempt to grab the lock and route data if there
+ // is actually data waiting in the DMA buffers to help the
+ // external IRQ retain higher priority access to process_routing
+ // IMPORTANT NOTE: the goal is to handle all data in the
+ // interrupts. This pathway to process_routing() is being provided
+ // as a fail safe. If it is regularly being used, consider this a
+ // warning sign of a broader system problem as it will cause slow
+ // link speeds.
+ if (drv_uart_has_dma_data())
+ try_process_routing(); // This try function is thread safe
+
+ // Handle LEDs using hardware cycle counts
+ if (DWT->CYCCNT - ledDelta >= cyclesPer250ms) {
+ ledDelta = DWT->CYCCNT;
+ drv_led_clear();
+
+ drv_led_on(1 << led);
+ drv_led_display();
+
+ if (++led >= DRV_LED_NUM_TOTAL) {
+ led = 0;
+ }
+ }
+ }
+}
+
+void HAL_MspInit(void)
+{
+ __HAL_RCC_PWR_CLK_ENABLE();
+ __HAL_RCC_SYSCFG_CLK_ENABLE();
+}
+
+void SysTick_Handler(void)
+{
+ HAL_IncTick();
+}
diff --git a/Mainboard/Firmware/motherboard_v1/Core/Src/stm32f7xx_it.c b/Mainboard/Firmware/mainboard/Core/Src/stm32f7xx_it.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Core/Src/stm32f7xx_it.c
rename to Mainboard/Firmware/mainboard/Core/Src/stm32f7xx_it.c
diff --git a/Mainboard/Firmware/motherboard_v1/Core/Src/syscalls.c b/Mainboard/Firmware/mainboard/Core/Src/syscalls.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Core/Src/syscalls.c
rename to Mainboard/Firmware/mainboard/Core/Src/syscalls.c
diff --git a/Mainboard/Firmware/motherboard_v1/Core/Src/sysmem.c b/Mainboard/Firmware/mainboard/Core/Src/sysmem.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Core/Src/sysmem.c
rename to Mainboard/Firmware/mainboard/Core/Src/sysmem.c
diff --git a/Mainboard/Firmware/motherboard_v1/Core/Src/system_stm32f7xx.c b/Mainboard/Firmware/mainboard/Core/Src/system_stm32f7xx.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Core/Src/system_stm32f7xx.c
rename to Mainboard/Firmware/mainboard/Core/Src/system_stm32f7xx.c
diff --git a/Mainboard/Firmware/motherboard_v1/Core/Startup/startup_stm32f765zgtx.s b/Mainboard/Firmware/mainboard/Core/Startup/startup_stm32f765zgtx.s
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Core/Startup/startup_stm32f765zgtx.s
rename to Mainboard/Firmware/mainboard/Core/Startup/startup_stm32f765zgtx.s
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Device/ST/STM32F7xx/Include/stm32f765xx.h b/Mainboard/Firmware/mainboard/Drivers/CMSIS/Device/ST/STM32F7xx/Include/stm32f765xx.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Device/ST/STM32F7xx/Include/stm32f765xx.h
rename to Mainboard/Firmware/mainboard/Drivers/CMSIS/Device/ST/STM32F7xx/Include/stm32f765xx.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Device/ST/STM32F7xx/Include/stm32f7xx.h b/Mainboard/Firmware/mainboard/Drivers/CMSIS/Device/ST/STM32F7xx/Include/stm32f7xx.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Device/ST/STM32F7xx/Include/stm32f7xx.h
rename to Mainboard/Firmware/mainboard/Drivers/CMSIS/Device/ST/STM32F7xx/Include/stm32f7xx.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Device/ST/STM32F7xx/Include/system_stm32f7xx.h b/Mainboard/Firmware/mainboard/Drivers/CMSIS/Device/ST/STM32F7xx/Include/system_stm32f7xx.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Device/ST/STM32F7xx/Include/system_stm32f7xx.h
rename to Mainboard/Firmware/mainboard/Drivers/CMSIS/Device/ST/STM32F7xx/Include/system_stm32f7xx.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/cmsis_armcc.h b/Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/cmsis_armcc.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/cmsis_armcc.h
rename to Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/cmsis_armcc.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/cmsis_armclang.h b/Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/cmsis_armclang.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/cmsis_armclang.h
rename to Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/cmsis_armclang.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/cmsis_compiler.h b/Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/cmsis_compiler.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/cmsis_compiler.h
rename to Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/cmsis_compiler.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/cmsis_gcc.h b/Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/cmsis_gcc.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/cmsis_gcc.h
rename to Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/cmsis_gcc.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/cmsis_iccarm.h b/Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/cmsis_iccarm.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/cmsis_iccarm.h
rename to Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/cmsis_iccarm.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/cmsis_version.h b/Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/cmsis_version.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/cmsis_version.h
rename to Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/cmsis_version.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/core_armv8mbl.h b/Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/core_armv8mbl.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/core_armv8mbl.h
rename to Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/core_armv8mbl.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/core_armv8mml.h b/Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/core_armv8mml.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/core_armv8mml.h
rename to Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/core_armv8mml.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/core_cm0.h b/Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/core_cm0.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/core_cm0.h
rename to Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/core_cm0.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/core_cm0plus.h b/Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/core_cm0plus.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/core_cm0plus.h
rename to Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/core_cm0plus.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/core_cm1.h b/Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/core_cm1.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/core_cm1.h
rename to Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/core_cm1.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/core_cm23.h b/Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/core_cm23.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/core_cm23.h
rename to Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/core_cm23.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/core_cm3.h b/Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/core_cm3.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/core_cm3.h
rename to Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/core_cm3.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/core_cm33.h b/Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/core_cm33.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/core_cm33.h
rename to Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/core_cm33.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/core_cm4.h b/Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/core_cm4.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/core_cm4.h
rename to Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/core_cm4.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/core_cm7.h b/Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/core_cm7.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/core_cm7.h
rename to Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/core_cm7.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/core_sc000.h b/Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/core_sc000.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/core_sc000.h
rename to Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/core_sc000.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/core_sc300.h b/Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/core_sc300.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/core_sc300.h
rename to Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/core_sc300.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/mpu_armv7.h b/Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/mpu_armv7.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/mpu_armv7.h
rename to Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/mpu_armv7.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/mpu_armv8.h b/Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/mpu_armv8.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/mpu_armv8.h
rename to Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/mpu_armv8.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/tz_context.h b/Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/tz_context.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/CMSIS/Include/tz_context.h
rename to Mainboard/Firmware/mainboard/Drivers/CMSIS/Include/tz_context.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal.h b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal.h
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_cortex.h b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_cortex.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_cortex.h
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_cortex.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_def.h b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_def.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_def.h
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_def.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_dma.h b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_dma.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_dma.h
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_dma.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_dma_ex.h b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_dma_ex.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_dma_ex.h
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_dma_ex.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_exti.h b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_exti.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_exti.h
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_exti.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_flash.h b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_flash.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_flash.h
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_flash.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_flash_ex.h b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_flash_ex.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_flash_ex.h
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_flash_ex.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_gpio.h b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_gpio.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_gpio.h
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_gpio.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_gpio_ex.h b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_gpio_ex.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_gpio_ex.h
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_gpio_ex.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_i2c.h b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_i2c.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_i2c.h
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_i2c.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_i2c_ex.h b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_i2c_ex.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_i2c_ex.h
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_i2c_ex.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_pwr.h b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_pwr.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_pwr.h
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_pwr.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_pwr_ex.h b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_pwr_ex.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_pwr_ex.h
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_pwr_ex.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_rcc.h b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_rcc.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_rcc.h
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_rcc.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_rcc_ex.h b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_rcc_ex.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_rcc_ex.h
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_rcc_ex.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_spi.h b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_spi.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_spi.h
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_spi.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_spi_ex.h b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_spi_ex.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_spi_ex.h
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_spi_ex.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_tim.h b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_tim.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_tim.h
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_tim.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_tim_ex.h b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_tim_ex.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_tim_ex.h
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_tim_ex.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_uart.h b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_uart.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_uart.h
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_uart.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_uart_ex.h b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_uart_ex.h
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_uart_ex.h
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Inc/stm32f7xx_hal_uart_ex.h
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal.c b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal.c
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal.c
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_cortex.c b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_cortex.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_cortex.c
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_cortex.c
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_dma.c b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_dma.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_dma.c
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_dma.c
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_dma_ex.c b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_dma_ex.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_dma_ex.c
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_dma_ex.c
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_exti.c b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_exti.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_exti.c
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_exti.c
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_flash.c b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_flash.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_flash.c
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_flash.c
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_flash_ex.c b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_flash_ex.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_flash_ex.c
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_flash_ex.c
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_gpio.c b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_gpio.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_gpio.c
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_gpio.c
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_i2c.c b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_i2c.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_i2c.c
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_i2c.c
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_i2c_ex.c b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_i2c_ex.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_i2c_ex.c
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_i2c_ex.c
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_pwr.c b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_pwr.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_pwr.c
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_pwr.c
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_pwr_ex.c b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_pwr_ex.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_pwr_ex.c
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_pwr_ex.c
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_rcc.c b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_rcc.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_rcc.c
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_rcc.c
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_rcc_ex.c b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_rcc_ex.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_rcc_ex.c
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_rcc_ex.c
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_spi.c b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_spi.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_spi.c
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_spi.c
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_spi_ex.c b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_spi_ex.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_spi_ex.c
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_spi_ex.c
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_tim.c b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_tim.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_tim.c
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_tim.c
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_tim_ex.c b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_tim_ex.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_tim_ex.c
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_tim_ex.c
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_uart.c b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_uart.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_uart.c
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_uart.c
diff --git a/Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_uart_ex.c b/Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_uart_ex.c
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_uart_ex.c
rename to Mainboard/Firmware/mainboard/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_uart_ex.c
diff --git a/Mainboard/Firmware/motherboard_v1/STM32F765ZGTX_FLASH.ld b/Mainboard/Firmware/mainboard/STM32F765ZGTX_FLASH.ld
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/STM32F765ZGTX_FLASH.ld
rename to Mainboard/Firmware/mainboard/STM32F765ZGTX_FLASH.ld
diff --git a/Mainboard/Firmware/motherboard_v1/STM32F765ZGTX_RAM.ld b/Mainboard/Firmware/mainboard/STM32F765ZGTX_RAM.ld
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/STM32F765ZGTX_RAM.ld
rename to Mainboard/Firmware/mainboard/STM32F765ZGTX_RAM.ld
diff --git a/Mainboard/Firmware/motherboard_v1/motherboard_v1.ioc b/Mainboard/Firmware/mainboard/mainboard.ioc
similarity index 99%
rename from Mainboard/Firmware/motherboard_v1/motherboard_v1.ioc
rename to Mainboard/Firmware/mainboard/mainboard.ioc
index 26496dc9..5e4ff89a 100644
--- a/Mainboard/Firmware/motherboard_v1/motherboard_v1.ioc
+++ b/Mainboard/Firmware/mainboard/mainboard.ioc
@@ -228,8 +228,8 @@ ProjectManager.MainLocation=Core/Src
ProjectManager.NoMain=false
ProjectManager.PreviousToolchain=STM32CubeIDE
ProjectManager.ProjectBuild=false
-ProjectManager.ProjectFileName=motherboard_v1.ioc
-ProjectManager.ProjectName=motherboard_v1
+ProjectManager.ProjectFileName=mainboard.ioc
+ProjectManager.ProjectName=mainboard
ProjectManager.StackSize=0x400
ProjectManager.TargetToolchain=STM32CubeIDE
ProjectManager.ToolChainLocation=
diff --git a/Mainboard/Firmware/motherboard_v1/scripts/check-format.sh b/Mainboard/Firmware/mainboard/scripts/check-format.sh
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/scripts/check-format.sh
rename to Mainboard/Firmware/mainboard/scripts/check-format.sh
diff --git a/Mainboard/Firmware/motherboard_v1/scripts/clang-format b/Mainboard/Firmware/mainboard/scripts/clang-format
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/scripts/clang-format
rename to Mainboard/Firmware/mainboard/scripts/clang-format
diff --git a/Mainboard/Firmware/motherboard_v1/scripts/format.sh b/Mainboard/Firmware/mainboard/scripts/format.sh
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/scripts/format.sh
rename to Mainboard/Firmware/mainboard/scripts/format.sh
diff --git a/Mainboard/Firmware/motherboard_v1/scripts/run-clang-format.py b/Mainboard/Firmware/mainboard/scripts/run-clang-format.py
similarity index 100%
rename from Mainboard/Firmware/motherboard_v1/scripts/run-clang-format.py
rename to Mainboard/Firmware/mainboard/scripts/run-clang-format.py
diff --git a/Mainboard/Firmware/motherboard_v1/.cproject b/Mainboard/Firmware/motherboard_v1/.cproject
deleted file mode 100644
index ac257487..00000000
--- a/Mainboard/Firmware/motherboard_v1/.cproject
+++ /dev/null
@@ -1,177 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Mainboard/Firmware/motherboard_v1/Core/Inc/adc.h b/Mainboard/Firmware/motherboard_v1/Core/Inc/adc.h
deleted file mode 100644
index 227d4b0d..00000000
--- a/Mainboard/Firmware/motherboard_v1/Core/Inc/adc.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef ADC_H
-#define ADC_H
-
-#include
-
-void adc_init(void);
-
-// Read the latest bits from the ADCs.
-//
-// Note that this is the RAW bits at the ADC output,
-// so the user must massage this into a usable value
-// for their application.
-//
-// This is a non-blocking function.
-//
-// The ADC sampling is happening in the background.
-// This function is guaranteed to return valid data,
-// but if it is called in the middle of an conversion,
-// one sample old data will be returned.
-void adc_latest_bits(uint16_t *output);
-
-#endif // ADC_H
diff --git a/Mainboard/Firmware/motherboard_v1/Core/Inc/drv_uart.h b/Mainboard/Firmware/motherboard_v1/Core/Inc/drv_uart.h
deleted file mode 100644
index 9be9a754..00000000
--- a/Mainboard/Firmware/motherboard_v1/Core/Inc/drv_uart.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef DRV_UART_H
-#define DRV_UART_H
-
-#include "platform.h"
-#include
-
-void drv_uart_init(void);
-
-static inline void drv_uart_putc_fast(USART_TypeDef *uart, uint8_t data)
-{
- // Wait until UART is ready to accept next character
- while (!(uart->ISR & UART_FLAG_TXE)) {
- asm("nop");
- }
-
- // Load the TDR register to send a character
- uart->TDR = data;
-}
-
-static inline void drv_uart_wait_TC(USART_TypeDef *uart)
-{
- // After done sending characters, must wait for TC flag!!
- while (!(uart->ISR & UART_FLAG_TC)) {
- asm("nop");
- }
-}
-
-static inline void drv_uart_send_fast(USART_TypeDef *uart, uint8_t *data, uint16_t len)
-{
- while (len > 0) {
- drv_uart_putc_fast(uart, *data);
- data++;
- len--;
- }
-
- drv_uart_wait_TC(uart);
-}
-
-#endif // DRV_UART_H
diff --git a/Mainboard/Firmware/motherboard_v1/Core/Inc/tx.h b/Mainboard/Firmware/motherboard_v1/Core/Inc/tx.h
deleted file mode 100644
index a55e8c85..00000000
--- a/Mainboard/Firmware/motherboard_v1/Core/Inc/tx.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef TX_H
-#define TX_H
-
-void transmit_samples(void);
-
-#endif // TX_H
diff --git a/Mainboard/Firmware/motherboard_v1/Core/Src/adc.c b/Mainboard/Firmware/motherboard_v1/Core/Src/adc.c
deleted file mode 100644
index 153ed98c..00000000
--- a/Mainboard/Firmware/motherboard_v1/Core/Src/adc.c
+++ /dev/null
@@ -1,231 +0,0 @@
-#include "adc.h"
-#include "drv_spi.h"
-#include "platform.h"
-#include "tx.h"
-#include
-#include
-
-static void setup_pin_SYNC_ADC(void);
-static void setup_pin_CONVST(void);
-
-// clang-format off
-
-#define NOP1 asm("nop")
-#define NOP2 NOP1;NOP1
-#define NOP4 NOP2;NOP2
-#define NOP8 NOP4;NOP4
-#define NOP16 NOP8;NOP8
-#define NOP32 NOP16;NOP16
-#define NOP64 NOP32;NOP32
-#define NOP128 NOP64;NOP64
-#define NOP256 NOP128;NOP128
-
-// clang-format on
-
-#define GPIO_SET_PIN(port, pin, x) port->BSRR = (x) ? pin : (pin << 16)
-
-#define SET_PIN_CONVST12_HIGH GPIO_SET_PIN(GPIOE, GPIO_PIN_10, 1)
-#define SET_PIN_CONVST34_HIGH GPIO_SET_PIN(GPIOE, GPIO_PIN_11, 1)
-#define SET_PIN_CONVST56_HIGH GPIO_SET_PIN(GPIOF, GPIO_PIN_6, 1)
-#define SET_PIN_CONVST78_HIGH GPIO_SET_PIN(GPIOG, GPIO_PIN_8, 1)
-
-#define SET_PIN_CONVST12_LOW GPIO_SET_PIN(GPIOE, GPIO_PIN_10, 0)
-#define SET_PIN_CONVST34_LOW GPIO_SET_PIN(GPIOE, GPIO_PIN_11, 0)
-#define SET_PIN_CONVST56_LOW GPIO_SET_PIN(GPIOF, GPIO_PIN_6, 0)
-#define SET_PIN_CONVST78_LOW GPIO_SET_PIN(GPIOG, GPIO_PIN_8, 0)
-
-#define ADC_FULL_SCALE (1 << 15)
-#define ADC_REF_VOLTAGE (4.096)
-#define ADC_VOLTS_PER_BIT ((float) ADC_REF_VOLTAGE / (float) ADC_FULL_SCALE)
-
-#define ADC_BITS_TO_VOLTS(bits) (ADC_VOLTS_PER_BIT * (float) bits)
-
-// Buffer of latest samples
-static volatile uint16_t latest_valid_adc_data[8] = { 0 };
-
-void adc_init(void)
-{
- // Setup output pin which starts ADC conversions
- setup_pin_CONVST();
-
- // Setup input pin which triggers ADC sampling (from AMDC)
- setup_pin_SYNC_ADC();
-}
-
-// NOTE: this function is called from the transmit function
-void adc_latest_bits(uint16_t *output)
-{
- volatile uint16_t *data = latest_valid_adc_data;
-
- // Give user their data (unrolled for speed)
- output[0] = data[0];
- output[1] = data[1];
- output[2] = data[2];
- output[3] = data[3];
- output[4] = data[4];
- output[5] = data[5];
- output[6] = data[6];
- output[7] = data[7];
-}
-
-static void adc_sample_all_daughtercards(uint16_t *sample_data_out)
-{
- // This function has been optimized for very
- // fast operation of all four SPI interfaces
- // to the daughter cards.
- //
- // It directly manipulates the four SPI peripherals'
- // registers to read in data from the ADCs. The ordering
- // of operations may look strange, but this is to minimize
- // wait time of the various APB interconnects in the MCU.
- //
- // The ADC devices support a max of 400ksps. Looking at
- // the waveforms from this function, the CONVST line is
- // asserted for effectively 280kHz... It could be faster,
- // but its not terrible...
-
- // Start all ADC conversions. We start them in order since
- // the ADC connected to CONVST12 will probably get done first.
- //
- // ADC conversion triggered by CONVST12 connects to SPI1
- // ADC conversion triggered by CONVST34 connects to SPI4
- // ADC conversion triggered by CONVST56 connects to SPI5
- // ADC conversion triggered by CONVST78 connects to SPI6
- SET_PIN_CONVST12_HIGH;
- SET_PIN_CONVST34_HIGH;
- SET_PIN_CONVST56_HIGH;
- SET_PIN_CONVST78_HIGH;
-
- // Wait for ADC conversion to complete (per datasheet, >= 1300ns
- // Each NOP takes 5ns, unrolled so branches don't affect timing...
- //
- // We need 260 NOPs
- NOP256;
- NOP4;
-
- // Smartly read all data from all ADCs at the same time.
- // This starts all the SPI peripherals effectively in parallel,
- // then waits for them to complete and gets the resulting data.
-
- // Start the SCLKs
- drv_spi_start_read_two_16bits(SPI1);
- drv_spi_start_read_two_16bits(SPI4);
- drv_spi_start_read_two_16bits(SPI5);
- drv_spi_start_read_two_16bits(SPI6);
-
- // Wait and read first ADC data
- //
- // The strange ordering of sample data indexing is
- // to correct for PCB layout pin swapping issues.
- drv_spi_finish_read_one_16bits(SPI1, &sample_data_out[3]);
- drv_spi_finish_read_one_16bits(SPI4, &sample_data_out[1]);
- drv_spi_finish_read_one_16bits(SPI5, &sample_data_out[0]);
- drv_spi_finish_read_one_16bits(SPI6, &sample_data_out[2]);
-
- // Wait for second ADC data to complete
- drv_spi_wait_for_RX(SPI1);
- drv_spi_wait_for_RX(SPI4);
- drv_spi_wait_for_RX(SPI5);
- drv_spi_wait_for_RX(SPI6);
-
- // End conversion
- SET_PIN_CONVST12_LOW;
- SET_PIN_CONVST34_LOW;
- SET_PIN_CONVST56_LOW;
- SET_PIN_CONVST78_LOW;
-
- // Read second ADC data
- drv_spi_get_DR(SPI1, &sample_data_out[7]);
- drv_spi_get_DR(SPI4, &sample_data_out[5]);
- drv_spi_get_DR(SPI5, &sample_data_out[4]);
- drv_spi_get_DR(SPI6, &sample_data_out[6]);
-}
-
-// This ISR is triggered by the AMDC to sync the ADC
-// conversions to the AMDC PWM carrier waveform. In
-// this ISR, all the motherboard ADCs should be sampled.
-void EXTI3_IRQHandler(void)
-{
- // Perform the actual SPI transactions
- uint16_t new_data[8] = { 0 };
- adc_sample_all_daughtercards(new_data);
-
- // Copy data into write buffer destination
- volatile uint16_t *dest = latest_valid_adc_data;
-
- // Unrolled loop for speed
- dest[0] = new_data[0];
- dest[1] = new_data[1];
- dest[2] = new_data[2];
- dest[3] = new_data[3];
- dest[4] = new_data[4];
- dest[5] = new_data[5];
- dest[6] = new_data[6];
- dest[7] = new_data[7];
-
- // Call the function in tx.c to transmit the sampled data back to the AMDC
- transmit_samples();
-
- // Clear all pending IRQs for ADC conversions at the
- // end of this ISR so that the system realigns the
- // ADC conversions with the SYNC signal from the AMDC.
- //
- // For some reason, this only works if we call both of these:
- NVIC_ClearPendingIRQ(EXTI3_IRQn);
- __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_3);
- NVIC_ClearPendingIRQ(EXTI3_IRQn);
-}
-
-static void setup_pin_CONVST(void)
-{
- GPIO_InitTypeDef GPIO_InitStruct = { 0 };
-
- __HAL_RCC_GPIOE_CLK_ENABLE();
- __HAL_RCC_GPIOF_CLK_ENABLE();
- __HAL_RCC_GPIOG_CLK_ENABLE();
-
- // Configure GPIO pin Output Level
- HAL_GPIO_WritePin(GPIOE, GPIO_PIN_10 | GPIO_PIN_11, GPIO_PIN_RESET);
- HAL_GPIO_WritePin(GPIOF, GPIO_PIN_6, GPIO_PIN_RESET);
- HAL_GPIO_WritePin(GPIOG, GPIO_PIN_8, GPIO_PIN_RESET);
-
- // Configure GPIO pins
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
-
- GPIO_InitStruct.Pin = GPIO_PIN_10 | GPIO_PIN_11;
- HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
-
- GPIO_InitStruct.Pin = GPIO_PIN_6;
- HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
-
- GPIO_InitStruct.Pin = GPIO_PIN_8;
- HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
-}
-
-static void setup_pin_SYNC_ADC(void)
-{
- // ADC Sync is a square wave input where every edge should
- // trigger a sampling event from the motherboard ADCs.
- //
- // These edges are aligned to the PWM carrier on the AMDC.
-
- GPIO_InitTypeDef GPIO_InitStruct = { 0 };
-
- __HAL_RCC_GPIOA_CLK_ENABLE();
-
- // Configure GPIO pin Output Level
- HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);
-
- // Configure GPIO pins
- GPIO_InitStruct.Pin = GPIO_PIN_3;
- GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
-
- // EXTI interrupt init
- HAL_NVIC_SetPriority(EXTI3_IRQn, 10, 0);
- HAL_NVIC_EnableIRQ(EXTI3_IRQn);
-}
diff --git a/Mainboard/Firmware/motherboard_v1/Core/Src/drv_uart.c b/Mainboard/Firmware/motherboard_v1/Core/Src/drv_uart.c
deleted file mode 100644
index c81c1767..00000000
--- a/Mainboard/Firmware/motherboard_v1/Core/Src/drv_uart.c
+++ /dev/null
@@ -1,123 +0,0 @@
-#include "drv_uart.h"
-#include "defines.h"
-#include "drv_clock.h"
-#include "platform.h"
-#include
-
-static void MX_USART_UART_Init(UART_HandleTypeDef *huart, USART_TypeDef *handle);
-
-static UART_HandleTypeDef huart2;
-static UART_HandleTypeDef huart3;
-
-void drv_uart_init(void)
-{
- // Twiddle some bits in the RCC module to set USART2 and USART3 clock source.
- // By default, the source is PCLK1 (i.e. APB1 clock), but this is 4x slower than
- // the system clock. We can configure the clock tree to use SYSCLK to get
- // higher data throughput!
- //
- // This feature is not really documented that well... :(
-
- __HAL_RCC_USART2_CONFIG(RCC_USART2CLKSOURCE_SYSCLK);
- __HAL_RCC_USART3_CONFIG(RCC_USART3CLKSOURCE_SYSCLK);
-
- MX_USART_UART_Init(&huart2, USART2);
- MX_USART_UART_Init(&huart3, USART3);
-}
-
-static void MX_USART_UART_Init(UART_HandleTypeDef *huart, USART_TypeDef *handle)
-{
- // Configure USART peripheral to run in transmit mode only, 8-bit data.
- //
- // Baud Rate: Each USART peripheral can be clocked from a variety of sources.
- // During uart_init() function, we set the clock tree mux such that USART2
- // and USART3 are now clocked by the system clock, which is configured to
- // 200 MHz via the PLL.
- //
- // If we configure our USART using oversampling of 8, we can get a max baud
- // rate of 200e6 / 8 = 25 Mbps
- uint32_t max_baudrate = SYSCLK_FREQ_HZ / 8; // 25 Mbps
-
- // Also, note that the AMDC FPGA is running at 200 MHz, so the fact that the
- // baud rate is an integer multiple of the FPGA clock is actually very nice!
- // This will make parsing data more robust on FPGA.
-
- huart->Instance = handle;
- huart->Init.BaudRate = max_baudrate;
- huart->Init.WordLength = UART_WORDLENGTH_9B;
- huart->Init.StopBits = UART_STOPBITS_2;
- huart->Init.Parity = UART_PARITY_ODD;
- huart->Init.Mode = UART_MODE_TX;
- huart->Init.HwFlowCtl = UART_HWCONTROL_NONE;
- huart->Init.OverSampling = UART_OVERSAMPLING_8;
- huart->Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
- huart->AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
-
- if (HAL_UART_Init(huart) != HAL_OK) {
- PANIC;
- }
-}
-
-void HAL_UART_MspInit(UART_HandleTypeDef *uartHandle)
-{
-
- GPIO_InitTypeDef GPIO_InitStruct = { 0 };
-
- if (uartHandle->Instance == USART2) {
- // USART2 clock enable
- __HAL_RCC_USART2_CLK_ENABLE();
-
- __HAL_RCC_GPIOA_CLK_ENABLE();
- // USART2 GPIO Configuration
- // PA2 ------> USART2_TX
- // PA3 ------> USART2_RX
- GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3;
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
- GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
- }
-
- else if (uartHandle->Instance == USART3) {
- // USART3 clock enable
- __HAL_RCC_USART3_CLK_ENABLE();
-
- __HAL_RCC_GPIOB_CLK_ENABLE();
- // USART3 GPIO Configuration
- // PB10 ------> USART3_TX
- // PB11 ------> USART3_RX
- GPIO_InitStruct.Pin = GPIO_PIN_10 | GPIO_PIN_11;
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
- GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
- HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
- }
-}
-
-void HAL_UART_MspDeInit(UART_HandleTypeDef *uartHandle)
-{
-
- if (uartHandle->Instance == USART2) {
- /* Peripheral clock disable */
- __HAL_RCC_USART2_CLK_DISABLE();
-
- /**USART2 GPIO Configuration
- PA2 ------> USART2_TX
- PA3 ------> USART2_RX
- */
- HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2 | GPIO_PIN_3);
- }
-
- else if (uartHandle->Instance == USART3) {
- /* Peripheral clock disable */
- __HAL_RCC_USART3_CLK_DISABLE();
-
- /**USART3 GPIO Configuration
- PB10 ------> USART3_TX
- PB11 ------> USART3_RX
- */
- HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10 | GPIO_PIN_11);
- }
-}
diff --git a/Mainboard/Firmware/motherboard_v1/Core/Src/main.c b/Mainboard/Firmware/motherboard_v1/Core/Src/main.c
deleted file mode 100644
index 851ce2be..00000000
--- a/Mainboard/Firmware/motherboard_v1/Core/Src/main.c
+++ /dev/null
@@ -1,67 +0,0 @@
-// Drivers
-#include "drv_clock.h"
-#include "drv_gpio.h"
-#include "drv_i2c.h"
-#include "drv_led.h"
-#include "drv_spi.h"
-#include "drv_uart.h"
-#include "platform.h"
-
-// Modules
-#include "adc.h"
-#include "tx.h"
-
-int main(void)
-{
- // Reset of all peripherals, Initializes the Flash interface and the Systick
- HAL_Init();
-
- // Configure the system clock
- drv_clock_init();
-
- // Initialize peripherals
- drv_spi_init();
- drv_uart_init();
- drv_led_init();
-
- // Initialize the main modules
- adc_init();
-
- // Infinite loop (all real work is done in ISRs)
- uint8_t led = 0;
-
- // Disable the SysTick ISR
- //
- // The SysTick ISR causes jitter in the firmware operation,
- // and since this project does not use the SysTick features,
- // we do not need it to run during operation!
- //
- // Set bit 0 to 0
- SysTick->CTRL &= 0xFFFFFFFE;
-
- while (1) {
- drv_led_clear();
- drv_led_on(1 << led);
- drv_led_display();
-
- if (++led >= DRV_LED_NUM_TOTAL) {
- led = 0;
- }
-
- volatile int i;
- for (i = 0; i < 10000000; i++) {
- asm("nop");
- }
- }
-}
-
-void HAL_MspInit(void)
-{
- __HAL_RCC_PWR_CLK_ENABLE();
- __HAL_RCC_SYSCFG_CLK_ENABLE();
-}
-
-void SysTick_Handler(void)
-{
- HAL_IncTick();
-}
diff --git a/Mainboard/Firmware/motherboard_v1/Core/Src/tx.c b/Mainboard/Firmware/motherboard_v1/Core/Src/tx.c
deleted file mode 100644
index b96477c1..00000000
--- a/Mainboard/Firmware/motherboard_v1/Core/Src/tx.c
+++ /dev/null
@@ -1,50 +0,0 @@
-#include "tx.h"
-#include "adc.h"
-#include "drv_uart.h"
-#include "platform.h"
-
-// Called after ADC conversions have been completed,
-// to send sampled data back to AMDC
-//
-void transmit_samples(void)
-{
- // Send header before we compute anything
- // to get the UART warmed up and running!
- uint8_t first_header = 0x90;
- drv_uart_putc_fast(USART2, first_header);
- drv_uart_putc_fast(USART3, first_header);
-
- // Get latest data from ADC driver (non-blocking)
- uint16_t bits[8];
- adc_latest_bits(bits);
-
- // Send data out over UART
- for (int i = 0; i < 4; i++) {
- uint16_t sample1 = bits[(4 * 0) + i];
- uint16_t sample2 = bits[(4 * 1) + i];
-
- // Send header (not the first one)
- if (i > 0) {
- // Send header as:
- // bits[7:2] = 100100
- // bits[1:0] = # of DC (2 bits, 0..3)
- uint8_t header = 0x90;
- header |= (0x03 & i);
-
- drv_uart_putc_fast(USART2, header);
- drv_uart_putc_fast(USART3, header);
- }
-
- // Send ADC sample data MSBs
- drv_uart_putc_fast(USART2, (uint8_t) (sample1 >> 8));
- drv_uart_putc_fast(USART3, (uint8_t) (sample2 >> 8));
-
- // Send ADC sample data LSBs
- drv_uart_putc_fast(USART2, (uint8_t) (sample1 & 0x00FF));
- drv_uart_putc_fast(USART3, (uint8_t) (sample2 & 0x00FF));
- }
-
- // Wait for entire UART transmission to complete
- drv_uart_wait_TC(USART2);
- drv_uart_wait_TC(USART3);
-}