diff options
author | Duncan Wilkie <antigravityd@gmail.com> | 2023-07-18 11:55:03 -0500 |
---|---|---|
committer | Duncan Wilkie <antigravityd@gmail.com> | 2023-07-18 11:55:03 -0500 |
commit | ed60865743a5d65240c9da353edb4dc20cf7009f (patch) | |
tree | bc7f7bb4ef3d48a1dfae42100667a5698d0b011e /controller | |
parent | 18a2be0c24b68dbfb4667e08ab6e8912adf52e7b (diff) |
Rename, add startup file.
Diffstat (limited to 'controller')
-rw-r--r-- | controller/Makefile | 4 | ||||
-rw-r--r-- | controller/inc/base_midi.h (renamed from controller/inc/midi.h) | 3 | ||||
-rw-r--r-- | controller/inc/startup.h | 173 | ||||
-rw-r--r-- | controller/libs/base_midi.c (renamed from controller/libs/midi.c) | 279 | ||||
-rw-r--r-- | controller/libs/startup.c | 225 | ||||
-rw-r--r-- | controller/src/main.c | 1 |
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() { |