--- /dev/null
+*.o
+*.elf
+*.hex
--- /dev/null
+MCU = atmega328p
+F_CPU = 16000000UL
+BAUD = 115200
+PROGRAMMER = arduino
+PORT = /dev/ttyACM0 # Change to your COM port if on Windows
+TARGET = multiFader
+
+CC = avr-gcc
+OBJCOPY = avr-objcopy
+AVRDUDE = avrdude
+
+CFLAGS = -Os -DF_CPU=$(F_CPU) -mmcu=$(MCU)
+
+all: $(TARGET).hex
+
+$(TARGET).o: $(TARGET).c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+$(TARGET).hex: $(TARGET).o
+ $(CC) $(CFLAGS) -o temp.elf $<
+ $(OBJCOPY) -O ihex -R .eeprom temp.elf $@
+ rm -f temp.elf
+
+flash: $(TARGET).hex
+ $(AVRDUDE) -c $(PROGRAMMER) -p $(MCU) -P $(PORT) -b $(BAUD) -U flash:w:$(TARGET).hex
+
+clean:
+ rm -f *.o *.hex
--- /dev/null
+#include <avr/io.h>
+#include <util/delay.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#define BAUD 31250
+#define MYUBRR ((F_CPU / (16UL * BAUD)) - 1)
+#define MIDI_CHANNEL 0
+#define NUM_CONTROLS 5
+#define BASE_CC 1 // Start at CC 1, increment for each
+
+const uint8_t pot_channels[NUM_CONTROLS] = {0, 1, 2, 3, 4}; // ADC0–ADC4
+const uint8_t mute_pins[NUM_CONTROLS] = {PD2, PD3, PD4, PD5, PD6}; // Digital mute pins
+
+uint8_t last_values[NUM_CONTROLS] = {255, 255, 255, 255, 255};
+bool muted[NUM_CONTROLS] = {false, false, false, false, false};
+
+void uart_init(unsigned int ubrr) {
+ UBRR0H = (unsigned char)(ubrr >> 8);
+ UBRR0L = (unsigned char)ubrr;
+ UCSR0B = (1 << TXEN0);
+ UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
+}
+
+void uart_send(uint8_t data) {
+ while (!(UCSR0A & (1 << UDRE0)));
+ UDR0 = data;
+}
+
+void send_midi_cc(uint8_t channel, uint8_t controller, uint8_t value) {
+ uart_send(0xB0 | (channel & 0x0F));
+ uart_send(controller);
+ uart_send(value);
+}
+
+void adc_init(void) {
+ ADMUX = (1 << REFS0); // AVcc
+ ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1); // Prescaler 64
+}
+
+uint16_t adc_read_channel(uint8_t channel) {
+ ADMUX = (ADMUX & 0xF0) | (channel & 0x0F); // Select ADCx
+ ADCSRA |= (1 << ADSC);
+ while (ADCSRA & (1 << ADSC));
+ return ADC;
+}
+
+void io_init(void) {
+ for (uint8_t i = 0; i < NUM_CONTROLS; i++) {
+ DDRD &= ~(1 << mute_pins[i]); // Input
+ PORTD |= (1 << mute_pins[i]); // Internal pull-up
+ }
+}
+
+int main(void) {
+ uart_init(MYUBRR);
+ adc_init();
+ io_init();
+
+ _delay_ms(500);
+
+ while (1) {
+ for (uint8_t i = 0; i < NUM_CONTROLS; i++) {
+ bool switch_state = !(PIND & (1 << mute_pins[i])); // Active LOW
+
+ if (switch_state && !muted[i]) {
+ // Mute just engaged
+ muted[i] = true;
+ send_midi_cc(MIDI_CHANNEL, BASE_CC + i, 0);
+ } else if (!switch_state && muted[i]) {
+ // Mute just released — send current value
+ muted[i] = false;
+ uint8_t val = adc_read_channel(pot_channels[i]) >> 3;
+ send_midi_cc(MIDI_CHANNEL, BASE_CC + i, val);
+ last_values[i] = val;
+ }
+
+ if (!muted[i]) {
+ uint8_t val = adc_read_channel(pot_channels[i]) >> 3;
+ if (abs((int)val - (int)last_values[i]) >= 2) {
+ send_midi_cc(MIDI_CHANNEL, BASE_CC + i, val);
+ last_values[i] = val;
+ }
+ }
+ }
+
+ _delay_ms(20); // Delay for debounce + noise filtering
+ }
+}
+
--- /dev/null
+:100000000C9434000C9451000C9451000C94510049\r
+:100010000C9451000C9451000C9451000C9451001C\r
+:100020000C9451000C9451000C9451000C9451000C\r
+:100030000C9451000C9451000C9451000C945100FC\r
+:100040000C9451000C9451000C9451000C945100EC\r
+:100050000C9451000C9451000C9451000C945100DC\r
+:100060000C9451000C94510011241FBECFEFD8E026\r
+:10007000DEBFCDBF11E0A0E0B1E0E8E7F2E002C0F2\r
+:1000800005900D92A031B107D9F721E0A0E1B1E0D0\r
+:1000900001C01D92A531B207E1F70E94B1000C9496\r
+:1000A0003A010C9400009093C5008093C40088E04E\r
+:1000B0008093C10086E08093C20008959091C000B3\r
+:1000C00095FFFCCF8093C6000895CF93DF93D62F82\r
+:1000D000C42F8F70806B0E945E008D2F0E945E0087\r
+:1000E0008C2FDF91CF910C945E0080E480937C0094\r
+:1000F00086E880937A00089590917C008F70907FBD\r
+:10010000892B80937C0080917A00806480937A00B0\r
+:1001100080917A0086FDFCCF8091780090917900E3\r
+:100120000895E5E0F1E041E050E02AB18191BA01A3\r
+:1001300002C0660F771F8A95E2F7CB018095822374\r
+:100140008AB98BB1DF012E91BA0102C0660F771F09\r
+:100150002A95E2F7862B8BB971E0EA30F70729F789\r
+:1001600008958FE190E00E9453000E9475000E9464\r
+:1001700091002FEF69E678E1215060407040E1F78F\r
+:1001800000C00000D1E025E0822E21E0922E30E177\r
+:10019000C32E31E0D32E40E0E42E41E0F42E5AE0AD\r
+:1001A000A52E51E0B52EC0E089B1F40131914F0187\r
+:1001B000F60121916F01CF5F90E002C09595879580\r
+:1001C0003A95E2F780FD1EC021110AC0D29340E0AB\r
+:1001D0006C2F80E00E946500F60182918115A1F0EC\r
+:1001E000FFEFEF1AFF0A2FEFA21AB20AC530E1F6AD\r
+:1001F0006FEF79EF80E0615070408040E1F700C020\r
+:100200000000C1CF211123C0F50180810E947C0034\r
+:100210008C0193E0169507959A95E1F7980133279D\r
+:10022000F7018081482F50E0602F681B770BCB01CE\r
+:1002300077FF03C0CA01821B930B02978CF2402FF9\r
+:100240006C2F80E00E946500F7010083C9CF1292F5\r
+:10025000F50180810E947C008C0183E01695079552\r
+:100260008A95E1F7402F6C2F80E00E946500F7012E\r
+:080270000083B2CFF894FFCF28\r
+:10027800FFFFFFFFFF02030405060001020304005D\r
+:00000001FF\r
--- /dev/null
+5-fader board