summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDuncan Wilkie <antigravityd@gmail.com>2023-07-18 11:55:03 -0500
committerDuncan Wilkie <antigravityd@gmail.com>2023-07-18 11:55:03 -0500
commited60865743a5d65240c9da353edb4dc20cf7009f (patch)
treebc7f7bb4ef3d48a1dfae42100667a5698d0b011e
parent18a2be0c24b68dbfb4667e08ab6e8912adf52e7b (diff)
Rename, add startup file.
-rw-r--r--controller/Makefile4
-rw-r--r--controller/inc/base_midi.h (renamed from controller/inc/midi.h)3
-rw-r--r--controller/inc/startup.h173
-rw-r--r--controller/libs/base_midi.c (renamed from controller/libs/midi.c)279
-rw-r--r--controller/libs/startup.c225
-rw-r--r--controller/src/main.c1
6 files changed, 546 insertions, 139 deletions
diff --git a/controller/Makefile b/controller/Makefile
index 00ed2da..9be9eb3 100644
--- a/controller/Makefile
+++ b/controller/Makefile
@@ -17,11 +17,11 @@ SRCS = $(wildcard src/*.c) \
OBJ = obj/
OBJS = $(addprefix $(OBJ),$(notdir $(SRCS:.c=.o)))
LD_SCRIPT = ld/$(MCU).ld
-IPATH = /home/dnw/Code/TivaC/libs
+IPATH = /home/dnw/Code/TivaC/libs/driverlib
# Flags.
CFLAGS = -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -ffunction-sections \
- -fdata-sections -MD -std=c99 -Wall -pedantic -DPART_${MCU} -c -Os -Dgcc -ggdb
+ -fdata-sections -MD -std=c2x -Wall -Wextra -Werror -DPART_${MCU} -c -Os -Dgcc -ggdb
CFLAGS += ${patsubst %,-I%,${subst :, ,${IPATH}}} -iquote inc
# Compiler/standard resource locations.
diff --git a/controller/inc/midi.h b/controller/inc/base_midi.h
index 819db03..e566a6f 100644
--- a/controller/inc/midi.h
+++ b/controller/inc/base_midi.h
@@ -6,7 +6,6 @@
#include <stddef.h>
// Configuration.
-
#define DEBUG 0 // If defined, enable input safety checking (e.g. too large data bytes, bad ID numbers, etc).
// These checks have some performance downside.
#define RUNNING_STATUS 0 // If defined, the MIDI instrument stores a transmit status and uses running statuses whenever possible.
@@ -67,7 +66,7 @@ typedef struct {
extern ConsumerBehavior pfns; // Initialize this globally in your main.
// System exclusive sends.
-void sysex(uint16_t manufacturer_id, bool long_id, uint8_t* contents, size_t contents_len);
+void sysex(uint16_t manufacturer_id, uint8_t* contents, size_t contents_len);
void universal_nonrealtime(uint8_t device_id, uint16_t sub_id, uint8_t* contents, size_t contents_len);
void universal_realtime(uint8_t device_id, uint16_t sub_id, uint8_t* contents, size_t contents_len);
diff --git a/controller/inc/startup.h b/controller/inc/startup.h
new file mode 100644
index 0000000..5e47193
--- /dev/null
+++ b/controller/inc/startup.h
@@ -0,0 +1,173 @@
+#ifndef STARTUP_H
+#define STARTUP_H
+/*
+* Copyright (c) 2018, Shawn D'silva <shawn@shawndsilva.com>
+* All rights reserved.
+*
+* This file is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+*
+* File: startup.c
+* Author: Shawn D'silva <https://www.shawndsilva.com>.
+* Version: 1.0.0.
+* Description: startup header for the TM4C Launchpad board,defines the vector table
+ handlers and ISRS,also declares external variables
+*/
+
+// +-----------------------------------------------------------------------------------+
+// + Type Definitions and Macros +
+// +-----------------------------------------------------------------------------------+
+
+/*
+ * Defines a macro DEFAULT that aliases the function prototype
+ * to Default_Handler if the function is not defined
+*/
+#define DEFAULT __attribute__((weak, alias("Default_Handler")))
+
+/* Defines a type for the ISR's in the vector table */
+typedef void (*element_t)(void);
+
+/* Defines a type for the vector table */
+typedef union {
+ element_t isr; //all ISRs use this type
+ void *stack_top; //pointer to top of the stack
+} vector_table_t;
+
+
+// +-----------------------------------------------------------------------------------+
+// + Prototypes of Basic Exception Handlers +
+// +-----------------------------------------------------------------------------------+
+
+//Default Handler,does nothing
+void Default_Handler(void);
+
+//System Exception Handlers
+
+void Reset_Handler(void);
+DEFAULT void NMI_Handler(void);
+DEFAULT void SVC_Handler(void);
+DEFAULT void DebugMonitor_Handler(void);
+DEFAULT void PendSV_Handler(void);
+DEFAULT void SysTick_Handler(void);
+
+//Fault Handlers
+
+DEFAULT void HardFault_Handler(void);
+DEFAULT void MemManageFault_Handler(void);
+DEFAULT void BusFault_Handler(void);
+DEFAULT void UsageFault_Handler(void);
+
+// +-----------------------------------------------------------------------------------+
+// + Prototypes of Interrupt Service Routines +
+// +-----------------------------------------------------------------------------------+
+DEFAULT void GPIOPortA_ISR(void);
+DEFAULT void GPIOPortB_ISR(void);
+DEFAULT void GPIOPortC_ISR(void);
+DEFAULT void GPIOPortD_ISR(void);
+DEFAULT void GPIOPortE_ISR(void);
+DEFAULT void UART0_ISR(void);
+DEFAULT void UART1_ISR(void);
+DEFAULT void SPI0_ISR(void);
+DEFAULT void I2C0_ISR(void);
+DEFAULT void PWM0Fault_ISR(void);
+DEFAULT void PWM0Generator0_ISR(void);
+DEFAULT void PWM0Generator1_ISR(void);
+DEFAULT void PWM0Generator2_ISR(void);
+DEFAULT void QEI0_ISR(void);
+DEFAULT void ADC0Sequence0_ISR(void);
+DEFAULT void ADC0Sequence1_ISR(void);
+DEFAULT void ADC0Sequence2_ISR(void);
+DEFAULT void ADC0Sequence3_ISR(void);
+DEFAULT void WatchDogTimer_ISR(void);
+DEFAULT void Timer0A_ISR(void);
+DEFAULT void Timer0B_ISR(void);
+DEFAULT void Timer1A_ISR(void);
+DEFAULT void Timer1B_ISR(void);
+DEFAULT void Timer2A_ISR(void);
+DEFAULT void Timer2B_ISR(void);
+DEFAULT void AnalogComparator0_ISR(void);
+DEFAULT void AnalogComparator1_ISR(void);
+DEFAULT void SystemCtrl_ISR(void);
+DEFAULT void FlashCtrl_ISR(void);
+DEFAULT void GPIOPortF_ISR(void);
+DEFAULT void UART2_ISR(void);
+DEFAULT void SPI1_ISR(void);
+DEFAULT void Timer3A_ISR(void);
+DEFAULT void Timer3B_ISR(void);
+DEFAULT void I2C1_ISR(void);
+DEFAULT void QEI1_ISR(void);
+DEFAULT void CAN0_ISR(void);
+DEFAULT void CAN1_ISR(void);
+DEFAULT void Hibernation_ISR(void);
+DEFAULT void USB0_ISR(void);
+DEFAULT void PWM0Generator3_ISR(void);
+DEFAULT void UDMASoftware_ISR(void);
+DEFAULT void UDMAError_ISR(void);
+DEFAULT void ADC1Sequence0_ISR(void);
+DEFAULT void ADC1Sequence1_ISR(void);
+DEFAULT void ADC1Sequence2_ISR(void);
+DEFAULT void ADC1Sequence3_ISR(void);
+DEFAULT void SPI2_ISR(void);
+DEFAULT void SPI3_ISR(void);
+DEFAULT void UART3_ISR(void);
+DEFAULT void UART4_ISR(void);
+DEFAULT void UART5_ISR(void);
+DEFAULT void UART6_ISR(void);
+DEFAULT void UART7_ISR(void);
+DEFAULT void I2C2_ISR(void);
+DEFAULT void I2C3_ISR(void);
+DEFAULT void Timer4A_ISR(void);
+DEFAULT void Timer4B_ISR(void);
+DEFAULT void Timer5A_ISR(void);
+DEFAULT void Timer5B_ISR(void);
+DEFAULT void WideTimer0A_ISR(void);
+DEFAULT void WideTimer0B_ISR(void);
+DEFAULT void WideTimer1A_ISR(void);
+DEFAULT void WideTimer1B_ISR(void);
+DEFAULT void WideTimer2A_ISR(void);
+DEFAULT void WideTimer2B_ISR(void);
+DEFAULT void WideTimer3A_ISR(void);
+DEFAULT void WideTimer3B_ISR(void);
+DEFAULT void WideTimer4A_ISR(void);
+DEFAULT void WideTimer4B_ISR(void);
+DEFAULT void WideTimer5A_ISR(void);
+DEFAULT void WideTimer5B_ISR(void);
+DEFAULT void SystemException_ISR(void);
+DEFAULT void PWM1Generator0_ISR(void);
+DEFAULT void PWM1Generator1_ISR(void);
+DEFAULT void PWM1Generator2_ISR(void);
+DEFAULT void PWM1Generator3_ISR(void);
+DEFAULT void PWM1Fault_ISR(void);
+
+// +-----------------------------------------------------------------------------------+
+// + External Variables declaration +
+// +-----------------------------------------------------------------------------------+
+
+//main() of your program
+extern int main(void);
+
+//stack pointer
+extern int _stack_ptr;
+//.text/code,stored in Flash
+extern int _etext;
+//.data,copied into RAM on boot
+extern int _data;
+extern int _edata;
+//.bss,unitialized variables
+extern int _bss;
+extern int _ebss;
+
+/***************************************** END OF FILE *******************************************/
+
+
+#endif
diff --git a/controller/libs/midi.c b/controller/libs/base_midi.c
index b718818..e146ec0 100644
--- a/controller/libs/midi.c
+++ b/controller/libs/base_midi.c
@@ -2,6 +2,8 @@
// Note the tables at its very end, with /absolutely no direct allusion in the text/.
#include "midi.h"
+#include <stdlib.h>
+#include <string.h>
#ifdef RUNNING_STATUS
uint8_t last_status = 0x00;
@@ -16,7 +18,7 @@ static inline void MIDI_bare_send(uint8_t status) {
}
#endif
- pfns->uart_write(status);
+ pfns.uart_write(status);
}
@@ -29,13 +31,13 @@ static inline void MIDI_single_send(uint8_t status, uint8_t byte) {
#ifdef RUNNING_STATUS
if (status != last_status) {
- pfns->uart_write(status);
+ pfns.uart_write(status);
last_status = status;
}
#else
- pfns->uart_write(status);
+ pfns.uart_write(status);
#endif
- pfns->uart_write(byte);
+ pfns.uart_write(byte);
}
static inline void MIDI_send(uint8_t status, uint8_t byte1, uint8_t byte2) {
@@ -47,14 +49,14 @@ static inline void MIDI_send(uint8_t status, uint8_t byte1, uint8_t byte2) {
#ifdef RUNNING_STATUS
if (status != last_status) {
- pfns->uart_write(status);
+ pfns.uart_write(status);
last_status = status;
}
#else
- pfns->uart_write(status);
+ pfns.uart_write(status);
#endif
- pfns->uart_write(byte1);
- pfns->uart_write(byte2);
+ pfns.uart_write(byte1);
+ pfns.uart_write(byte2);
}
@@ -68,7 +70,7 @@ void sysex(uint16_t manufacturer_id, uint8_t* contents, size_t contents_len) {
}
// Pretty inefficient to iterate contents twice, but prevents writing partial SysEx messages to the bus.
- for (int i = 0; i < contents_len, i++) {
+ for (size_t i = 0; i < contents_len; i++) {
if (contents[i] > MAX_DATA_BYTE) {
while(true);
}
@@ -76,50 +78,51 @@ void sysex(uint16_t manufacturer_id, uint8_t* contents, size_t contents_len) {
#endif
if ((manufacturer_id >> 8) != 0) {
- pfns->uart_write(SYSEX_STATUS);
- pfns->uart_write(0x00);
- pfns->uart_write(manufacturer_id >> 8);
- pfns->uart_write(manufacturer_id & 0x00ff);
+ pfns.uart_write(SYSEX_STATUS);
+ pfns.uart_write(0x00);
+ pfns.uart_write(manufacturer_id >> 8);
+ pfns.uart_write(manufacturer_id & 0x00ff);
} else {
if (manufacturer_id > MAX_NON_UNIVERSAL_ID) {
while(true); // Used universal sysex ID.
}
- pfns->uart_write(manufacturer_id);
+ pfns.uart_write(manufacturer_id);
}
- for (int i = 0; i < message.contents_len; i++) {
- pfns->uart_write(message.contents[i]);
+ for (size_t i = 0; i < contents_len; i++) {
+ pfns.uart_write(contents[i]);
}
- pfns->uart_write(EOX_STATUS);
+ pfns.uart_write(EOX_STATUS);
}
-#define NON_REAL_TIME_ID 0x7e
-#define REAL_TIME_ID 0x7f
+#define UNIVERSAL_NONREALTIME_SUBID 0x7e
+#define UNIVERSAL_REALTIME_SUBID 0x7f
void universal_nonrealtime(uint8_t device_id, uint16_t sub_id, uint8_t *contents, size_t contents_len) {
#ifdef DEBUG
if ((sub_id >> 8) > MAX_DATA_BYTE || (sub_id & 0x00ff) > MAX_DATA_BYTE) {
while(true);
}
- for (int i = 0; i < contents_len; i++) {
+ for (size_t i = 0; i < contents_len; i++) {
if (contents[i] > MAX_DATA_BYTE) {
while(true);
}
}
#endif
- pfns->uart_write(SYSEX_STATUS);
- pfns->uart_write(REAL_TIME_ID);
- pfns->uart_write(sub_id >> 8);
- pfns->uart_write(sub_id & 0x00ff);
+ pfns.uart_write(SYSEX_STATUS);
+ pfns.uart_write(UNIVERSAL_NONREALTIME_SUBID);
+ pfns.uart_write(device_id);
+ pfns.uart_write(sub_id >> 8);
+ pfns.uart_write(sub_id & 0x00ff);
- for (int i = 0; i < message.contents_len; i++) {
- pfns->uart_write(message.contents[i]);
+ for (size_t i = 0; i < contents_len; i++) {
+ pfns.uart_write(contents[i]);
}
- pfns->uart_write(EOX_STATUS);
+ pfns.uart_write(EOX_STATUS);
}
void universal_realtime(uint8_t device_id, uint16_t sub_id, uint8_t *contents, size_t contents_len) {
@@ -128,23 +131,24 @@ void universal_realtime(uint8_t device_id, uint16_t sub_id, uint8_t *contents, s
while(true);
}
- for (int i = 0; i < contents_len; i++) {
+ for (size_t i = 0; i < contents_len; i++) {
if (contents[i] > MAX_DATA_BYTE) {
while(true);
}
}
#endif
- pfns->uart_write(SYSEX_STATUS);
- pfns->uart_write(NON_REAL_TIME_ID);
- pfns->uart_write(sub_id >> 8);
- pfns->uart_write(sub_id & 0x00ff);
+ pfns.uart_write(SYSEX_STATUS);
+ pfns.uart_write(UNIVERSAL_REALTIME_SUBID);
+ pfns.uart_write(device_id);
+ pfns.uart_write(sub_id >> 8);
+ pfns.uart_write(sub_id & 0x00ff);
- for (int i = 0; i < message.contents_len; i++) {
- pfns->uart_write(message.contents[i]);
+ for (size_t i = 0; i < contents_len; i++) {
+ pfns.uart_write(contents[i]);
}
- pfns->uart_write(EOX_STATUS);
+ pfns.uart_write(EOX_STATUS);
}
// Channel voice messages.
@@ -222,7 +226,7 @@ void note_off(uint8_t channel, uint8_t note) {
#define MAX_CONTROLLER 119
void control_change(uint8_t channel, uint8_t controller_number, uint8_t control_value) {
#ifdef DEBUG
- if (channel > MAX_CHANNEL || controller_number > MAX_CONTROLLER_NUMBER || control_value > MAX_DATA_BYTE) {
+ if (channel > MAX_CHANNEL || controller_number > MAX_CONTROLLER || control_value > MAX_DATA_BYTE) {
while(true);
}
#endif
@@ -255,12 +259,12 @@ void aftertouch(uint8_t channel, uint8_t pressure_value) {
void pitch_bend_change(uint8_t channel, uint16_t pressure_value) {
#ifdef DEBUG
- if (channel > MAX_CHANNEL || pressure_value > (MAX_DATA_BYTE << 8) | MAX_DATA_BYTE) {
+ if (channel > MAX_CHANNEL || pressure_value > ((MAX_DATA_BYTE << 8) | MAX_DATA_BYTE)) {
while(true);
}
#endif
- MIDI_single_send(PITCH_BEND_CHANGE_MASK | channel, pressure_value);
+ MIDI_single_send(PITCH_BEND_MASK | channel, pressure_value);
}
@@ -328,7 +332,7 @@ void all_notes_off(uint8_t channel) {
}
#endif
- MIDI_send(CONTROL_CHANGE_MASK | channel, NOTES_OFF_MODE, 0)
+ MIDI_send(CONTROL_CHANGE_MASK | channel, NOTES_OFF_MODE, 0);
}
@@ -391,7 +395,7 @@ void poly_on(uint8_t channel) {
void song_position_pointer(uint16_t position) {
#ifdef DEBUG
- if (position & 0x0ff > MAX_DATA_BYTE || position >> 8 > MAX_DATA_BYTE) {
+ if ((position & 0x0ff) > MAX_DATA_BYTE || (position >> 8) > MAX_DATA_BYTE) {
while(true);
}
#endif
@@ -475,7 +479,7 @@ void bulk_tuning_dump_request(uint8_t device_id, uint8_t program) {
uint8_t contents[] = {program};
- universal_nonrealtime(device_id, TUNING_STANDARD_SUBID, BULK_DUMP_REQUEST_SUBID, contents, 1);
+ universal_nonrealtime(device_id, (TUNING_STANDARD_SUBID << 8) | BULK_DUMP_REQUEST_SUBID, contents, 1);
}
@@ -494,14 +498,14 @@ void bulk_tuning_dump(uint8_t device_id, uint8_t program, char* name, uint8_t* t
memcpy(contents + 1 + TUNING_NAME_LENGTH, tuning_data, TUNING_LENGTH);
// I hate this freaking "standard"...what TF do I checksum???
- uint8_t checksum = NON_REAL_TIME_ID ^ device_id ^ TUNING_STANDARD_SUBID ^ BULK_DUMP_REPLY_SUBID ^ program;
+ uint8_t checksum = UNIVERSAL_NONREALTIME_SUBID ^ device_id ^ TUNING_STANDARD_SUBID ^ BULK_DUMP_REPLY_SUBID ^ program;
for (int i = 0; i < TUNING_LENGTH; i++) {
checksum ^= tuning_data[i];
}
contents[1 + TUNING_NAME_LENGTH + DEVICE_KEY_COUNT] = checksum;
- universal_nonrealtime(device_id, TUNING_STANDARD_SUBID, BULK_DUMP_REPLY_SUBID, contents,
+ universal_nonrealtime(device_id, (TUNING_STANDARD_SUBID << 8) | BULK_DUMP_REPLY_SUBID, contents,
1 + TUNING_NAME_LENGTH + TUNING_LENGTH + 1);
free(contents);
@@ -521,7 +525,7 @@ void single_note_tuning_change(uint8_t device_id, uint8_t program, uint8_t *note
contents[1] = keys_changed;
memcpy(contents + 2, note_tuning_data, NOTE_TUNING_BYTES_PER_KEY * keys_changed);
- universal_realtime(device_id, TUNING_STANDARD_SUBID, NOTE_CHANGE_SUBID, contents,
+ universal_realtime(device_id, (TUNING_STANDARD_SUBID << 8) | NOTE_CHANGE_SUBID, contents,
2 + NOTE_TUNING_BYTES_PER_KEY * keys_changed);
free(contents);
@@ -539,7 +543,7 @@ typedef struct {
uint8_t byte0;
bool send_eox;
uint8_t *stack;
- uint8_t top;
+ size_t top;
size_t size;
} ParserMemory;
@@ -548,41 +552,46 @@ ParserMemory memory = {.status = WAITING_FOR_STATUS,
.first_byte = false,
.byte0 = 0x00,
.send_eox = false,
- .stack = malloc(128),
+ .stack = NULL, // TODO: initialize from main.
.top = 0,
.size = 128};
-static inline void push(uint8_t val) {
- if (memory->top == memory->size - 1) {
- memory->stack = realloc(memory->stack, memory->size + 128);
+static inline void push_fn(uint8_t val) {
+ if (memory.top == memory.size - 1) {
+ memory.stack = realloc(memory.stack, memory.size + 128);
}
- memory->stack[memory->top + 1] = val;
- ++memory->top;
+ memory.stack[memory.top + 1] = val;
+ ++memory.top;
}
+#define push() do { \
+ push_fn(byte); \
+ } while(0)
+
static inline uint8_t pop() {
- if (memory->size - memory->top > 128) {
- memory->stack = realloc(memory->stack, memory->size - 128);
+ if (memory.size - memory.top > 128) {
+ memory.stack = realloc(memory.stack, memory.size - 128);
}
- --memory->top;
- return memory->stack[memory->top + 1];
+ --memory.top;
+ return memory.stack[memory.top + 1];
}
static inline void reset() {
- memory->stack = realloc(memory->stack, 128);
- memory->size = 128;
- memory->top = 0;
- memory->status = WAITING_FOR_STATUS;
+ memory.stack = realloc(memory.stack, 128);
+ memory.size = 128;
+ memory.top = 0;
+ memory.status = WAITING_FOR_STATUS;
}
-static inline void second_byte() {
- memory->first_data_byte = false;
- memory->byte0 = byte;
-}
+#define second_byte() do { \
+ memory.first_byte = false; \
+ memory.byte0 = byte; \
+ } while(0)
+
-#define channel (memory->status & 0x0f)
+#define channel (memory.status & 0x0f)
// Memory should be large enough to handle the largest message that's expected to be processed automatically here.
@@ -590,178 +599,178 @@ void parse_midi_stream(uint8_t byte) {
switch (byte) {
// Status byte.
case NOTE_OFF_MASK ... (PITCH_BEND_MASK + MAX_CHANNEL):
- memory->status = byte;
+ memory.status = byte;
break;
case MTC_QUARTER_FRAME_STATUS ... SONG_SELECT_STATUS:
- memory->status = byte;
+ memory.status = byte;
break;
case TUNE_REQUEST_STATUS:
- pfns->tune_request_handler();
- memory->status = WAITING_FOR_STATUS;
+ pfns.tune_request_handler();
+ memory.status = WAITING_FOR_STATUS;
break;
case TIMING_CLOCK_STATUS:
- pfns->timing_clock_handler();
+ pfns.timing_clock_handler();
break;
case START_STATUS:
- pfns->start_handler();
+ pfns.start_handler();
break;
case CONTINUE_STATUS:
- pfns->continue_handler();
+ pfns.continue_handler();
break;
case STOP_STATUS:
- pfns->stop_handler();
+ pfns.stop_handler();
break;
case ACTIVE_SENSING_STATUS:
- pfns->active_sensing_handler();
+ pfns.active_sensing_handler();
break;
case SYSTEM_RESET_STATUS:
- pfns->system_reset_handler();
+ pfns.system_reset_handler();
break;
case SYSEX_STATUS:
- memory->status = byte;
+ memory.status = byte;
break;
case EOX_STATUS:
- if (memory->send_eox) {
- pfns->end_of_sysex_handler();
- memory->send_eox = false;
+ if (memory.send_eox) {
+ pfns.end_of_sysex_handler();
+ memory.send_eox = false;
}
reset();
break;
// Data byte.
case 0x00 ... MAX_DATA_BYTE:
- switch (memory->status) {
+ switch (memory.status) {
case WAITING_FOR_STATUS:
break;
case NOTE_OFF_MASK ... (NOTE_OFF_MASK + MAX_CHANNEL):
- if (memory->first_data_byte)
+ if (memory.first_byte)
second_byte();
else {
- pfns->note_off_handler(channel, memory->byte0, byte);
- memory->first_data_byte = true;
+ pfns.note_off_handler(channel, memory.byte0, byte);
+ memory.first_byte = true;
}
break;
case NOTE_ON_MASK ... (NOTE_ON_MASK + MAX_CHANNEL):
- if (memory->first_data_byte)
+ if (memory.first_byte)
second_byte();
else {
- pfns->note_on_handler(channel, memory->byte0, byte);
- memory->first_data_byte = true;
+ pfns.note_on_handler(channel, memory.byte0, byte);
+ memory.first_byte = true;
}
break;
case POLY_KEY_PRESSURE_MASK ... (POLY_KEY_PRESSURE_MASK + MAX_CHANNEL):
- if (memory->first_data_byte)
+ if (memory.first_byte)
second_byte();
else {
- pfns->poly_key_handler(channel, memory->byte0, byte);
- memory->first_data_byte = true;
+ pfns.poly_key_handler(channel, memory.byte0, byte);
+ memory.first_byte = true;
}
break;
case CONTROL_CHANGE_MASK ... (CONTROL_CHANGE_MASK + MAX_CHANNEL):
- if (memory->first_data_byte):
+ if (memory.first_byte)
second_byte();
else {
- switch (memory->byte0) {
+ switch (memory.byte0) {
case 0x00 ... MAX_CONTROLLER:
- pfns->control_change_handler(channel);
+ pfns.control_change_handler(channel, memory.byte0, byte);
break;
case SOUND_OFF_MODE:
- pfns->all_sound_off_handler(channel);
+ pfns.all_sound_off_handler(channel);
break;
case RESET_ALL_MODE:
- pfns->reset_all_controllers_handler(channel);
+ pfns.reset_all_controllers_handler(channel);
break;
case LOCAL_CONTROL_MODE:
- pfns->local_control_handler(channel);
+ pfns.local_control_handler(channel, byte);
break;
case NOTES_OFF_MODE:
- pfns->all_notes_off_handler(channel);
+ pfns.all_notes_off_handler(channel);
break;
case OMNI_OFF_MODE:
- pfns->omni_off_handler(channel);
+ pfns.omni_off_handler(channel);
break;
case OMNI_ON_MODE:
- pfns->omni_on_handler(channel);
+ pfns.omni_on_handler(channel);
break;
case MONO_ON_MODE:
- pfns->mono_on_handler(channel, byte);
+ pfns.mono_on_handler(channel, byte);
break;
case POLY_ON_MODE:
- pfns->poly_on_handler(channel);
+ pfns.poly_on_handler(channel);
break;
default:
while(true); // Should be unreachable.
}
- memory->first_data_byte = true;
+ memory.first_byte = true;
}
break;
case PROGRAM_CHANGE_MASK ... (PROGRAM_CHANGE_MASK + MAX_CHANNEL):
- pfns->program_change_handler(channel, byte);
+ pfns.program_change_handler(channel, byte);
break;
case AFTERTOUCH_MASK ... (AFTERTOUCH_MASK + MAX_CHANNEL):
- pfns->aftertouch_handler(channel, byte);
+ pfns.aftertouch_handler(channel, byte);
break;
case PITCH_BEND_MASK ... (PITCH_BEND_MASK + MAX_CHANNEL):
- pfns->pitch_bend_change_handler(channel, byte);
+ pfns.pitch_bend_change_handler(channel, byte);
break;
case MTC_QUARTER_FRAME_STATUS:
- if (memory->first_data_byte)
+ if (memory.first_byte)
second_byte();
else {
- pfns->mtc_quarter_frame_handler(memory->byte0, byte);
- memory->first_data_byte = true;
+ pfns.mtc_quarter_frame_handler(memory.byte0, byte);
+ memory.first_byte = true;
}
break;
case SONG_POSITION_POINTER_STATUS:
- if (memory->first_data_byte)
+ if (memory.first_byte)
second_byte();
else {
- pfns->song_position_pointer_handler(memory->byte0, byte);
- memory->first_data_byte = true;
+ pfns.song_position_pointer_handler(memory.byte0, byte);
+ memory.first_byte = true;
}
break;
case SONG_SELECT_STATUS:
- song_select_handler(byte);
+ pfns.song_select_handler(byte);
break;
case SYSEX_STATUS:
- if (memory->first_data_byte) {
+ if (memory.first_byte) {
reset(); // In case last sysex got interrupted by a status.
if (byte <= MAX_NON_UNIVERSAL_ID)
- pfns->sysex_collector(byte);
+ pfns.sysex_collector(byte);
second_byte();
} else
- switch (memory->byte0) {
+ switch (memory.byte0) {
case UNIVERSAL_NONREALTIME_SUBID:
push();
- if (memory->top > 2) {
- uint8_t device_id = memory->stack[0];
- uint8_t subid1 = memory->stack[1];
- uint8_t subid2 = memory->stack[2];
+ if (memory.top > 2) {
+ uint8_t device_id = memory.stack[0];
+ uint8_t subid1 = memory.stack[1];
+ uint8_t subid2 = memory.stack[2];
switch (subid1) {
case TUNING_STANDARD_SUBID:
switch (subid2) {
case BULK_DUMP_REQUEST_SUBID:
- pfns->bulk_tuning_dump_request_handler(device_id, byte);
+ pfns.bulk_tuning_dump_request_handler(device_id, byte);
reset();
break;
case BULK_DUMP_REPLY_SUBID:
- if (memory->top == 4 + TUNING_NAME_LENGTH + TUNING_LENGTH - 1) {
- uint8_t tuning_program = memory->stack[3];
- uint8_t checksum = NON_REAL_TIME_ID ^ device_id ^ TUNING_STANDARD_SUBID \
+ if (memory.top == 4 + TUNING_NAME_LENGTH + TUNING_LENGTH - 1) {
+ uint8_t tuning_program = memory.stack[3];
+ uint8_t checksum = UNIVERSAL_NONREALTIME_SUBID ^ device_id ^ TUNING_STANDARD_SUBID \
^ BULK_DUMP_REPLY_SUBID ^ tuning_program;
for (int i = 0; i < TUNING_LENGTH; i++) {
- checksum ^= memory->stack[4 + TUNING_NAME_LENGTH - 1 + i];
+ checksum ^= memory.stack[4 + TUNING_NAME_LENGTH - 1 + i];
}
- if (memory->stack[memory->top] == checksum) {
- pfns->bulk_tuning_dump_handler(memory->stack[0], memory->stack[3], memory->stack + 4,
- memory->stack + 4 + TUNING_NAME_LENGTH);
+ if (memory.stack[memory.top] == checksum) {
+ pfns.bulk_tuning_dump_handler(memory.stack[0], memory.stack[3], (char *)(memory.stack + 4),
+ memory.stack + 4 + TUNING_NAME_LENGTH);
}
reset();
@@ -771,7 +780,7 @@ void parse_midi_stream(uint8_t byte) {
}
break;
default:
- if (!pfns->unimplemented_universal_sysex_collector(byte)) {
+ if (!pfns.unimplemented_universal_sysex_collector(byte)) {
reset();
} else {
push();
@@ -783,18 +792,18 @@ void parse_midi_stream(uint8_t byte) {
case UNIVERSAL_REALTIME_SUBID:
push();
- if (memory->top > 2) {
- uint8_t device_id = memory->stack[0];
- uint8_t subid1 = memory->stack[1];
- uint8_t subid2 = memory->stack[2];
+ if (memory.top > 2) {
+ uint8_t device_id = memory.stack[0];
+ uint8_t subid1 = memory.stack[1];
+ uint8_t subid2 = memory.stack[2];
switch (subid1) {
case TUNING_STANDARD_SUBID:
switch (subid2) {
case NOTE_CHANGE_SUBID:
- uint8_t program_number = memory->stack[3];
- uint8_t change_count = memory->stack[4];
- if (memory->top >= 4 && memory->top == 4 + change_count + 1 - 1) {
- pfns->single_note_tuning_change_handler(device_id, program_number, change_count, memory->stack + 5);
+ uint8_t program_number = memory.stack[3];
+ uint8_t change_count = memory.stack[4];
+ if (memory.top >= 4 && memory.top == 4 + (size_t)change_count + 1 - 1) {
+ pfns.single_note_tuning_change_handler(device_id, program_number, change_count, memory.stack + 5);
reset();
}
break;
@@ -808,7 +817,7 @@ void parse_midi_stream(uint8_t byte) {
}
break;
default:
- if (!pfns->sysex_collector(byte)) {
+ if (!pfns.sysex_collector(byte)) {
reset();
} else {
push();
diff --git a/controller/libs/startup.c b/controller/libs/startup.c
new file mode 100644
index 0000000..7c7b77a
--- /dev/null
+++ b/controller/libs/startup.c
@@ -0,0 +1,225 @@
+/*
+* Copyright (c) 2018, Shawn D'silva <shawn@shawndsilva.com>
+* All rights reserved.
+*
+* This file is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+*
+* File: startup.c
+* Author: Shawn D'silva <https://www.shawndsilva.com>.
+* Version: 1.0.0.
+* Description: startup file for the TM4C Launchpad board,defines the vector table,
+ and most importantly the Reset_Handler enabling the TM4C to execute the main program when the <RESET>
+ button is pressed on board
+*/
+#include "startup.h"
+
+// +-----------------------------------------------------------------------------------+
+// + Vector Table +
+// +-----------------------------------------------------------------------------------+
+
+__attribute__((section(".vector_table"))) //marks this vector table as a part of the section "".vector_table"
+//in the linker script
+const vector_table_t vectors[] = {
+ {.stack_top = &_stack_ptr}, // 0 Pointer to top of Stack
+ {.isr = Reset_Handler}, // 1 Reset handler is called when the <RESET> button is pressed
+ {.isr = NMI_Handler}, // 2 Non-Maskable Interrupt handler
+ {.isr = HardFault_Handler}, // 3 Hard Fault Handler
+ {.isr = MemManageFault_Handler}, // 4 Memory management fault Handler
+ {.isr = BusFault_Handler}, // 5 Bus Fault Handler
+ {.isr = UsageFault_Handler}, // 6 Usage Fault Handler
+ {.isr = 0}, // 7 Reserved
+ {.isr = 0}, // 8 Reserved
+ {.isr = 0}, // 9 Reserved
+ {.isr = 0}, // 10 Reserved
+ {.isr = SVC_Handler}, // 11 SuperVisor Call Handler
+ {.isr = DebugMonitor_Handler}, // 12 Debug Monitor Handler
+ {.isr = 0}, // 13 Reserved
+ {.isr = PendSV_Handler}, // 14 Pendeable interrupt driven request
+ {.isr = SysTick_Handler}, // 15 SysTick Timer handler
+ {.isr = GPIOPortA_ISR}, // 16 GPIO Port A Interrupt Service Routine
+ {.isr = GPIOPortB_ISR}, // 17 GPIO Port B Interrupt Service Routine
+ {.isr = GPIOPortC_ISR}, // 18 GPIO Port C Interrupt Service Routine
+ {.isr = GPIOPortD_ISR}, // 19 GPIO Port D Interrupt Service Routine
+ {.isr = GPIOPortE_ISR}, // 20 GPIO Port C Interrupt Service Routine
+ {.isr = UART0_ISR}, // 21 UART 0
+ {.isr = UART1_ISR}, // 22 UART 1
+ {.isr = SPI0_ISR}, // 23 SPI 0
+ {.isr = I2C0_ISR},
+ {.isr = PWM0Fault_ISR},
+ {.isr = PWM0Generator0_ISR},
+ {.isr = PWM0Generator1_ISR},
+ {.isr = PWM0Generator2_ISR},
+ {.isr = QEI0_ISR},
+ {.isr = ADC0Sequence0_ISR},
+ {.isr = ADC0Sequence1_ISR},
+ {.isr = ADC0Sequence2_ISR},
+ {.isr = ADC0Sequence3_ISR},
+ {.isr = WatchDogTimer_ISR},
+ {.isr = Timer0A_ISR},
+ {.isr = Timer0B_ISR},
+ {.isr = Timer1A_ISR},
+ {.isr = Timer1B_ISR},
+ {.isr = Timer2A_ISR},
+ {.isr = Timer2B_ISR},
+ {.isr = AnalogComparator0_ISR},
+ {.isr = AnalogComparator1_ISR},
+ {.isr = 0},
+ {.isr = SystemCtrl_ISR},
+ {.isr = FlashCtrl_ISR},
+ {.isr = GPIOPortF_ISR},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = UART2_ISR},
+ {.isr = SPI1_ISR},
+ {.isr = Timer3A_ISR},
+ {.isr = Timer3B_ISR},
+ {.isr = I2C1_ISR},
+ {.isr = QEI1_ISR},
+ {.isr = CAN0_ISR},
+ {.isr = CAN1_ISR},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = Hibernation_ISR},
+ {.isr = USB0_ISR},
+ {.isr = PWM0Generator3_ISR},
+ {.isr = UDMASoftware_ISR},
+ {.isr = UDMAError_ISR},
+ {.isr = ADC1Sequence0_ISR},
+ {.isr = ADC1Sequence1_ISR},
+ {.isr = ADC1Sequence2_ISR},
+ {.isr = ADC1Sequence3_ISR},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = SPI2_ISR},
+ {.isr = SPI3_ISR},
+ {.isr = UART3_ISR},
+ {.isr = UART4_ISR},
+ {.isr = UART5_ISR},
+ {.isr = UART6_ISR},
+ {.isr = UART7_ISR},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = I2C2_ISR},
+ {.isr = I2C3_ISR},
+ {.isr = Timer4A_ISR},
+ {.isr = Timer4B_ISR},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0}, // 95 Reserved
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = Timer5A_ISR},
+ {.isr = Timer5B_ISR},
+ {.isr = WideTimer0A_ISR},
+ {.isr = WideTimer0B_ISR},
+ {.isr = WideTimer1A_ISR},
+ {.isr = WideTimer1B_ISR},
+ {.isr = WideTimer2A_ISR},
+ {.isr = WideTimer2B_ISR},
+ {.isr = WideTimer3A_ISR},
+ {.isr = WideTimer3B_ISR},
+ {.isr = WideTimer4A_ISR},
+ {.isr = WideTimer4B_ISR},
+ {.isr = WideTimer5A_ISR},
+ {.isr = WideTimer5B_ISR},
+ {.isr = SystemException_ISR},
+ {.isr = 0}, //123 Reserved
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = 0},
+ {.isr = PWM1Generator0_ISR},
+ {.isr = PWM1Generator1_ISR},
+ {.isr = PWM1Generator2_ISR},
+ {.isr = PWM1Generator3_ISR},
+ {.isr = PWM1Fault_ISR},
+};
+
+// +-----------------------------------------------------------------------------------+
+// + Implementations of Interrupt Service Routines +
+// +-----------------------------------------------------------------------------------+
+void Reset_Handler(void)
+{
+
+ int *src, *dest;
+
+ /* copying of the .data values into RAM */
+
+ src = &_etext;
+ for (dest = &_data; dest < &_edata;)
+ {
+ *dest++ = *src++;
+ }
+
+ /* initializing .bss values to zero*/
+
+ for (dest = &_bss; dest < &_ebss;)
+ {
+ *dest++ = 0;
+ }
+
+ /* your program's main() called */
+ main();
+}
+
+void Default_Handler(void)
+{
+ while (1)
+ {
+ //does literally nothing except infinitely loop
+ }
+}
+
+/*****************************************END OF FILE*********************************************/
diff --git a/controller/src/main.c b/controller/src/main.c
index 1650499..fb3f18a 100644
--- a/controller/src/main.c
+++ b/controller/src/main.c
@@ -1,4 +1,5 @@
#include "midi.h"
+#include "uart.h"
int main() {