From 1fd366764d17874b8211ef63d41313995833e36d Mon Sep 17 00:00:00 2001 From: Duncan Wilkie Date: Fri, 14 Jul 2023 11:17:59 -0500 Subject: The start-ish of it all. --- controller/.projectile | 0 controller/Makefile | 62 ++++++++ controller/ld/TM4C123GH6PM.ld | 72 +++++++++ controller/libs/midi.c | 347 ++++++++++++++++++++++++++++++++++++++++++ controller/src/main.c | 5 + 5 files changed, 486 insertions(+) create mode 100644 controller/.projectile create mode 100644 controller/Makefile create mode 100644 controller/ld/TM4C123GH6PM.ld create mode 100644 controller/libs/midi.c create mode 100644 controller/src/main.c (limited to 'controller') diff --git a/controller/.projectile b/controller/.projectile new file mode 100644 index 0000000..e69de29 diff --git a/controller/Makefile b/controller/Makefile new file mode 100644 index 0000000..fef034d --- /dev/null +++ b/controller/Makefile @@ -0,0 +1,62 @@ +# A spec for using Tivaware's makefiles + +# Top-level concerns. +PROJECT = controller +MCU = TM4C123GH6PM + +# Utilities. +CC = arm-none-eabi-gcc +LD = arm-none-eabi-ld +OBJCOPY = arm-none-eabi-objcopy +RM = rm -rf +MKDIR = @mkdir -p $(@D) + +# Custom/TI/build resource locations. +SRCS = $(wildcard src/*.c) \ + $(wildcard libs/*.c) +OBJ = obj/ +OBJS = $(addprefix $(OBJ),$(notdir $(SRCS:.c=.o))) +LD_SCRIPT = ld/$(MCU).ld +IPATH = /home/dnw/Code/TivaC/libs + +# 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 +CFLAGS += ${patsubst %,-I%,${subst :, ,${IPATH}}} -Iinc + +# Compiler/standard resource locations. +LIBGCC := ${shell ${CC} ${CFLAGS} -print-libgcc-file-name} +LIBC := ${shell ${CC} ${CFLAGS} -print-file-name=libc.a} +LIBM := ${shell ${CC} ${CFLAGS} -print-file-name=libm.a} + +# More flags. +LDFLAGS = -T $(LD_SCRIPT) -e Reset_Handler --gc-sections '${LIBGCC}' '${LIBC}' '${LIBM}' + + + + + +# Targets. +all: bin/$(PROJECT).bin + +$(OBJ)%.o: src/%.c + $(MKDIR) + $(CC) -o $@ $^ $(CFLAGS) + +$(OBJ)%.o: libs/%.c + $(MKDIR) + $(CC) -o $@ $^ $(CFLAGS) + +$(info $$PROJECT is [${PROJECT}]) +bin/$(PROJECT).elf: $(OBJS) + $(MKDIR) + $(LD) -o $@ $^ $(LDFLAGS) + +bin/$(PROJECT).bin: bin/$(PROJECT).elf + $(OBJCOPY) -O binary $< $@ + +clean: + -$(RM) obj + -$(RM) bin + +.PHONY: all clean diff --git a/controller/ld/TM4C123GH6PM.ld b/controller/ld/TM4C123GH6PM.ld new file mode 100644 index 0000000..29ff8d8 --- /dev/null +++ b/controller/ld/TM4C123GH6PM.ld @@ -0,0 +1,72 @@ +/* +* Copyright (c) 2018, Shawn D'silva +* 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 . +* +* File: TM4C123GH6PHM.ld +* Author: Shawn D'silva . +* Version: 1.0.0. +* Description: linker file for the TM4C Launchpad +*/ + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 256K /* FLASH size 256KB */ + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 32K/* RAM size 32KB */ + +} + +SECTIONS +{ + + + /* + * initial stack pointer pointing to top of stack,starts from higher addresses + * i.e ORIGIN(RAM) + LENGTH(RAM)-1 in this case 0x20007FFF to lower addesses i.e + * those lesser than 0x20007FFF to 0x2000000,which is the origina address of RAM, + * until it comes in contact with .bss or .data in which case a buffer overflow occurs + */ + PROVIDE( _stack_ptr = ORIGIN(RAM) + LENGTH(RAM)); + + /* constants and other code stored in FLASH */ + .text : + { + _text = .; /* beginning of .text segment,also called code memory */ + KEEP(*(.vector_table)) /* vector table defined in startup.c to be included */ + *(.text*) /* other code */ + *(.rodata*) /* constants go here */ + _etext = .; /* end of .text segment */ + } > FLASH + + /* data, initialized variables, to be copied to RAM upon by startup.c */ + .data : + { + _data = .; /* beginning of .data segment */ + *(.data*) /* data goes here */ + _edata = .; /* end of .data segment */ + } > RAM AT >FLASH /* .data segment starts directly after the .text section in FLASH */ + + /* uninitialized data which is initialized to 0 upon by startup.c */ + .bss : + { + _bss = .; /* beginning of .bss segment */ + *(.bss*) /* .bss content goes here */ + *(COMMON) + _ebss = .; /* end of .bss segment */ + } > RAM + + + +} diff --git a/controller/libs/midi.c b/controller/libs/midi.c new file mode 100644 index 0000000..488b172 --- /dev/null +++ b/controller/libs/midi.c @@ -0,0 +1,347 @@ +// This file is written to be read side-along with the MIDI 1.0 spec. +// Note the tables at its very end, with /absolutely no direct allusion in the text/. + +#include +#include + +typedef struct { + uint8_t len; + uint8_t status; + uint8_t data1; + uint8_t data2; +} MIDIMessage; + +typedef struct { + uint8_t status; + uint8_t sub_id; + uint8_t* bytes; + uint8_t size; +} SysExMessage; + + + +// Channel voice messages. + +#IFDEF KEY_ON_VELOCITY + +MIDIMessage note_on(uint8_t channel, uint8_t note, uint8_t velocity) { + if (channel > 0x0f || note > 127 || velocity > 127) { + while(1); + } + + return {.status = 0x90 & channel, + .data1 = note, + .data2 = velocity + .len = 3}; +} + +#ELSE + +MIDIMessage note_on(uint8_t channel, uint8_t note) { + if (channel > 0x0f || note > 127) { + while(1); + } + + return {.status = 0x90 & channel, + .data1 = note, + .data2 = 0x40 + .len = 3}; +} + + +#ENDIF + +#IFDEF RELEASE_VELOCITY + +MIDIMessage note_off(uint8_t channel, uint8_t note, uint8_t velocity) { + if (channel > 0x0f || note > 127 || velocity > 127) { + while(1); + } + + return {.status = 0x80 & channel, + .data1 = note, + .data2 = velocity + .len = 3}; +} + +#ELSE + +#IFDEF ACTUAL_OFF_MESSAGE + +MIDIMessage note_off(uint8_t channel, uint8_t note) { + if (channel > 0x0f || note > 127) { + while(1); + } + + return {.status = 0x80 & channel, + .data1 = note, + .data2 = 0x40 + .len = 3}; +} + +#ELSE + +MIDIMessage note_off(uint8_t channel, uint8_t note) { + if (channel > 0x0f || note > 127) { + while(1); + } + + return {.status = 0x90 & channel, + .data1 = note, + .data2 = 0 + .len = 3}; +} + +#ENDIF +#ENDIF + +MIDIMessage control_change(uint8_t channel, uint8_t control_number, uint8_t control_value) { + if (channel > 0x0f || control_number > 119 || control_value > 127) { + while(1); + } + + return {.status = 0xb0 & channel, + .data1 = control_number, + .data2 = control_value + .len = 3}; +} + +enum Controller { + bank_select = 0, + modulation_wheel = 1, + breath_controller = 2, + // undefined + foot_controller = 4, + portamento_time = 5, + data_entry_msb = 6, + channel_volume = 7, + balance = 8, + // undefined + pan = 10, + expression = 11, + effect1 = 12, + effect2 = 13, + // undefined + gp1 = 16, + gp2 = 17, + gp3 = 18, + gp4 = 19, + damper_pedal = 64, + portamento_toggle = 65, + sostenuto = 66, + soft_pedal = 67, + legato_footswitch = 68, + hold2 = 69, + sc1_sound_variation = 70, + sc2_timbre = 71, + sc3_release_time = 72, + sc4_attack_time = 73, + sc5_brightness = 74, + sc6 = 75, + sc7 = 76, + sc8 = 77, + sc9 = 78, + sc10 = 79, + gp5 = 80, + gp6 = 81, + gp7 = 82, + gp8 = 83, + portamento_control = 84, + // undefined + effects_depth1 = 91, + effects_depth2 = 92, + effects_depth3 = 93, + effects_depth4 = 94, + effects_depth5 = 95, + data_increment = 96, + data_decrement = 97, + nonregistered_lsb = 98, + nonregistered_msb = 99, + registered_lsb = 100, + regustered_msg = 101, + // undefined 102-119 + // channel mode 120-127 +}; + +enum RegisteredParams { + pitch_bend_sensitivity = 0, + fine_tuning = 1, + coarse_tuning = 2, + tuning_program_select = 3, + tuning_bank_select = 4 +}; + + +MIDIMessage program_change(uint8_t channel, uint8_t program_number) { + if (channel > 0x0f || program_number > 119) { + while(1); + } + + return {.status = 0xc0 & channel, + .data1 = program_number, + .len = 2}; +} + +MIDIMessage aftertouch(uint8_t channel, uint8_t pressure_value) { + if (channel > 0x0f || pressure_value > 127) { + while(1); + } + + return {.status = 0xd0 & channel, + .data1 = pressure_value, + .len = 2}; +} + +MIDIMessage pitch_bend_change(uint8_t channel, uint16_t change) { + if (channel > 0x0f || pressure_value < 0x40 || pressure_value > 0x7f7f) { + while(1); + } + + return {.status = 0xe0 & channel, + .data1 = pressure_value, + .len = 2}; +} + +// Channel mode messages. + + +MIDIMessage all_sound_off(uint8_t channel) { + if (channel > 0x0f) { + while(1); + } + + return {.status = 0xb0 & channel, + .data1 = 120, + .data2 = 0}; +} + +MIDIMessage reset_all_controllers(uint8_t channel) { + if (channel > 0x0f) { + while(1); + } + + return {.status = 0xb0 & channel, + .data1 = 121, + .data2 = 0}; +} + +MIDIMessage local_control(uint8_t channel, bool status) { + if (channel > 0x0f) { + while(1); + } + + if (status) { + return {.status = 0xb0 & channel, + .data1 = 122, + .data2 = 127}; + } else { + return {.status = 0xb0 & channel, + .data1 = 122, + .data2 = 0}; + } +} + +MIDIMessage all_notes_off(uint8_t channel) { + if (channel > 0x0f) { + while(1); + } + + return {.status = 0xb0 & channel, + .data1 = 123, + .data2 = 0}; +} + +MIDIMessage omni_toggle(uint8_t channel, bool status) { + if (channel > 0x0f) { + while(1); + } + + if (status) { + return {.status = 0xb0 & channel, + .data1 = 125, + .data2 = 0}; + } else { + return {.status = 0xb0 & channel, + .data1 = 124, + .data2 = 0}; + } +} + +#define RECEIVER_CHANNEL_COUNT 0 +MIDIMessage mono_on(uint8_t channel, uint8_t channel_count) { + if (channel > 0x0f || channel_count > 127) { + while(1); + } + + return {.status = 0xb0 & channel, + .data1 = 126, + .data2 = channel_count}; +} + +MIDIMessage poly_on(uint8_t channel) { + if (channel > 0x0f) { + while(1); + } + + return {.status = 0xb0 & channel, + .data1 = 127, + .data2 = 0}; +} + + +// System common messages. +// Not implemented: +// - MTC Quarter Frame, +// - Song Position Pointer, +// - Song Select, +// - Tune Request. + +const MIDIMessage eox = {.status = 0xf7, .len = 1}; + + +// System real time messages. +// Not implemented: +// - Timing Clock, +// - Start, +// - Continue, +// - Stop, +// - Active Sensing, + +MIDIMessage rst = {.status = 0xff, .len = 1}; + + +// System exclusive messages. + +SysExMessage sysex(uint8_t sub_id, uint8_t* contents, size_t size) { + if (sub_id > 127) { + while(1); + } + + return {.status = 0xf0, + .sub_id = sub_id, + .data = contents, + .size = size}; +} + +// Only implement MIDI Tuning Standard universals +// and general information. + +SysExMessage universal_sysex(uint8_t sub_id1, uint8_t sub_id2, uint8_t* contents, size_t size, bool real_time) { + if (sub_id1 > 127 || sub_id2 > 127) { + while(1); + } + + uint8_t* new = malloc(contents, size + 2); // Might forget to free this... + new[0] = sub_id1; + new[1] = subid2; + memcpy(new + 2, contents, size); + + + if (real_time) { + return sysex(0x7e, new, size + 2); + } else { + return sysex(0x7e, new, size + 2); + } +} + +SysExMessage bulk_tuning_dump(uint8_t) diff --git a/controller/src/main.c b/controller/src/main.c new file mode 100644 index 0000000..800f691 --- /dev/null +++ b/controller/src/main.c @@ -0,0 +1,5 @@ +#include "uart.h" + +int main() { + +} -- cgit v1.2.3