Added firmware

This commit is contained in:
2025-01-05 14:21:49 +01:00
parent f5010308ed
commit 5eacfa13bc
3 changed files with 501 additions and 0 deletions

View File

@@ -0,0 +1,219 @@
#include <Arduino.h>
#define FADER1 A0
#define SR_DATA A5 //19
#define SR_CLOCK 5
#define SR_LATCH A4 //18
#define MTX_I 2 //18
bool last_button_state[80];
/*
UART-Init:
Berechnung des Wertes für das Baudratenregister
aus Taktrate und gewünschter Baudrate
*/
#ifndef F_CPU
#define F_CPU 16000000UL
#endif
/// CONFIG
#define BAUD 19200UL // Baudrate
#define CHANNEL 4 // midi channel
#define OFFSET 0 // first midi note
// Berechnungen
#define UBRR_VAL ((F_CPU + BAUD * 8) / (BAUD * 16) - 1) // clever runden
#define BAUD_REAL (F_CPU / (16 * (UBRR_VAL + 1))) // Reale Baudrate
#define BAUD_ERROR ((BAUD_REAL * 1000) / BAUD) // Fehler in Promille, 1000 = kein Fehler.
#if ((BAUD_ERROR < 990) || (BAUD_ERROR > 1010))
#error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch!
#endif
void setup() {
// prints title with ending line break
for (int i = 0; i < 80; i++) {
last_button_state[i] = 0;
}
//DDRB |= 0b00111111; // PORT_A contains matrix rows 1-2
//DDRD |= 0b11000000; // PORT_B contains matrix rows 3-8
pinMode(SR_DATA, OUTPUT);
pinMode(SR_CLOCK, OUTPUT);
pinMode(SR_LATCH, OUTPUT);
pinMode(MTX_I, OUTPUT);
//pinMode(12, OUTPUT); // 1
//pinMode(11, OUTPUT); // 2
//pinMode(2, OUTPUT); // 3
//pinMode(3, OUTPUT); // 4
//pinMode(4, OUTPUT); // 5
//pinMode(5, OUTPUT); // 6
//pinMode(6, OUTPUT); // 7
//pinMode(7, OUTPUT); // 8
//pinMode(8, INPUT); // A
//pinMode(9, INPUT); // B
//pinMode(10, INPUT); // V
// init uart
UBRR0 = UBRR_VAL;
UCSR0B |= (1 << TXEN0);
UCSR0B |= (1 << RXEN0);
// Frame Format: Asynchron 8N1
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
UCSR0B |= (1 << RXCIE0);
sei();
}
int uart_putc(unsigned char c) {
while (!(UCSR0A & (1 << UDRE0))) /* warten bis Senden moeglich */
{
}
UDR0 = c; /* sende Zeichen */
return 0;
}
// first visible ASCIIcharacter '!' is number 33:
int thisByte = 33;
// you can also write ASCII characters in single quotes.
// for example, '!' is the same as 33, so you could also use this:
// int thisByte = '!';
uint8_t noteON = B10010000;
uint8_t noteOFF = B10000000;
int last_fader[1] = { 0 };
int pins_fader[1] = { FADER1 };
char buttons[3] = { 'A', 'B', 'C' };
char in_msg[63]; //ringbuffer for incomming midi
uint16_t in_index_last = 0;
uint16_t in_index_top = 0;
long int lastin = 0;
int in_last = 0;
void loop() {
processAnalog();
//processQueue();
processMatrix();
//processQueue();
}
uint8_t start_ch = OFFSET;
void midi_put_buffer(char data) {
//clear buffer if last tx is 1 sec ago
long int now = millis();
if (now - lastin > 1000) {
in_index_top = 0;
in_index_last = 0;
}
lastin = now;
in_msg[in_index_top] = data;
in_index_top++;
if (in_index_top >= 63) {
in_index_top = 0;
}
}
void midi_send_buffer_single() {
uint16_t diff = 0;
if (in_index_top < in_index_last) {
diff = (63 + in_index_top) - in_index_last;
} else {
diff = in_index_top - in_index_last;
}
if (diff > 2) {
uart_putc(in_msg[in_index_last + 0]);
uart_putc(in_msg[in_index_last + 1]);
uart_putc(in_msg[in_index_last + 2]);
in_index_last += 3;
if (in_index_last >= 63) {
in_index_last -= 63;
}
}
}
ISR(USART_RX_vect) {
unsigned char b;
b = UDR0;
midi_put_buffer(b);
}
void processQueue() {
midi_send_buffer_single();
}
void processAnalog() {
for (int i = 0; i < 1; i++) {
int val = analogRead(pins_fader[i]);
if (val - last_fader[i] > 2 || val - last_fader[i] < -2) {
sendMessageNote(CHANNEL, 1 + i, map(val, 1, 1022, 127, 0));
last_fader[i] = val;
} else if ((val < 2 && last_fader[i] > 2) || (val > 1022 && last_fader[i] < 1022)) {
sendMessageNote(CHANNEL, 1 + i, map(val, 1, 1022, 127, 0));
last_fader[i] = val;
}
}
}
void srClock(uint8_t bit) {
digitalWrite(SR_DATA, bit);
digitalWrite(SR_CLOCK, 1);
digitalWrite(SR_CLOCK, 0);
digitalWrite(SR_LATCH, 1);
digitalWrite(SR_LATCH, 0);
}
void processMatrix() {
srClock(1); //shift 1st byte
for (int i = 0; i < 9; i++) {
if (i == 8) {
digitalWrite(MTX_I, HIGH);
} else {
digitalWrite(MTX_I, LOW);
}
int baseId = i * 8;
uint8_t data = getMatrix();
for (int b = 0; b < 8; b++) {
bool state = ((data & _BV(b)) > 0);
if (state != last_button_state[baseId + b]) {
last_button_state[baseId + b] = state;
sendMessageNote(CHANNEL, 2 + baseId + b, state ? 127 : 0);
}
}
//shift 0 byte
srClock(0);
}
}
uint8_t getMatrix() {
uint8_t val1 = PINB & 0b00111111;
uint8_t val2 = PIND & 0b11000000;
return (val1 | val2);
}
void sendMessageNote(uint8_t channel, uint8_t note, int velocity) {
uint8_t statusByte = (velocity > 0 ? noteON : noteOFF) & 0xF0;
statusByte |= channel & 0x0F;
uart_putc(statusByte);
uart_putc(start_ch + note);
uart_putc(velocity);
}

View File

@@ -0,0 +1,226 @@
#include <Arduino.h>
#define FADER1 A0
#define FADER2 A1
#define FADER3 A2
#define FADER4 A3
#define FADER5 A4
bool last_button_state[30];
int last_button_time[30];
/*
UART-Init:
Berechnung des Wertes für das Baudratenregister
aus Taktrate und gewünschter Baudrate
*/
#ifndef F_CPU
#define F_CPU 16000000UL // Systemtakt in Hz - Definition als unsigned long beachten
// Ohne ergeben sich unten Fehler in der Berechnung
#endif
/// CONFIG
#define BAUD 19200UL // Baudrate
#define CHANNEL 1 // midi channel
#define OFFSET 60 // first midi note
// Berechnungen
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) // clever runden
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) // Reale Baudrate
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
#error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch!
#endif
void setup() {
for (int i = 0; i < 30; i++) {
last_button_state[i] = 0;
last_button_time[i] = 0;
}
DDRB &= 0b11111000; // PORT_A contains matrix col 1-3
DDRB |= 0b00011000; // PORT_A contains matrix rows 1-2
DDRD |= 0b11111100; // PORT_B contains matrix rows 3-8
PORTB &= ~(1 << PB0);
PORTB &= ~(1 << PB1);
PORTB &= ~(1 << PB2);
//pinMode(12, OUTPUT); // 1
//pinMode(11, OUTPUT); // 2
//pinMode(2, OUTPUT); // 3
//pinMode(3, OUTPUT); // 4
//pinMode(4, OUTPUT); // 5
//pinMode(5, OUTPUT); // 6
//pinMode(6, OUTPUT); // 7
//pinMode(7, OUTPUT); // 8
//pinMode(8, INPUT); // A
//pinMode(9, INPUT); // B
//pinMode(10, INPUT); // V
// init uart
UBRR0 = UBRR_VAL;
UCSR0B |= (1<<TXEN0);
UCSR0B |= (1<<RXEN0);
// Frame Format: Asynchron 8N1
UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
UCSR0B |= (1<<RXCIE0);
sei();
}
int uart_putc(unsigned char c)
{
while (!(UCSR0A & (1<<UDRE0))) /* warten bis Senden moeglich */
{
}
UDR0 = c; /* sende Zeichen */
return 0;
}
// first visible ASCIIcharacter '!' is number 33:
int thisByte = 33;
// you can also write ASCII characters in single quotes.
// for example, '!' is the same as 33, so you could also use this:
// int thisByte = '!';
uint8_t noteON = B10010000;
uint8_t noteOFF = B10000000;
int last_fader[5] = { 0, 0, 0, 0, 0 };
int pins_fader[5] = { FADER1, FADER2, FADER3, FADER4, FADER5 };
char buttons[3] = { 'A', 'B', 'C' };
char in_msg[63]; //ringbuffer for incomming midi
uint16_t in_index_last = 0;
uint16_t in_index_top = 0;
long int lastin = 0;
int in_last = 0;
void loop() {
processAnalog();
processQueue();
processMatrix();
processQueue();
}
uint8_t start_ch = OFFSET;
void midi_put_buffer(char data){
//clear buffer if last tx is 1 sec ago
long int now = millis();
if (now - lastin > 1000){
in_index_top = 0;
in_index_last = 0;
}
lastin = now;
in_msg[in_index_top] = data;
in_index_top++;
if ( in_index_top >= 63){
in_index_top = 0;
}
}
void midi_send_buffer_single(){
uint16_t diff = 0;
if (in_index_top < in_index_last){
diff = (63 + in_index_top) - in_index_last;
}else{
diff = in_index_top - in_index_last;
}
if (diff > 2){
uart_putc(in_msg[in_index_last + 0]);
uart_putc(in_msg[in_index_last + 1]);
uart_putc(in_msg[in_index_last + 2]);
in_index_last += 3;
if (in_index_last >= 63){
in_index_last -= 63;
}
}
}
ISR(USART_RX_vect)
{
unsigned char b;
b=UDR0;
midi_put_buffer(b);
}
void processQueue(){
midi_send_buffer_single();
}
void processAnalog() {
for (int i = 0; i < 5; i++) {
int val = analogRead(pins_fader[i]);
if (val - last_fader[i] > 2 || val - last_fader[i] < -2) {
sendMessageNote(1, 1 + i, map(val, 1, 1022, 127, 0));
last_fader[i] = val;
}else if ((val < 2 && last_fader[i] >= 2) || (val > 1022 && last_fader[i] <= 1022)){
sendMessageNote(1, 1 + i, map(val, 1, 1022, 127, 0));
last_fader[i] = val;
}
}
}
void processMatrix() {
for (int i = 0; i < 8; i++) {
int baseId = i * 3;
uint8_t data = putMatrixCol(i);
bool state1 = ((data & 1) > 0);
bool state2 = ((data & 2) > 0);
bool state3 = ((data & 4) > 0);
//Serial.println(baseId);
if (state1 != last_button_state[baseId + 0]) {
last_button_state[baseId + 0] = state1;
sendMessageNote(1, 6 + baseId + 0, state1 ? 127:0);
}
if (state2 != last_button_state[baseId + 1]) {
last_button_state[baseId + 1] = state2;
sendMessageNote(1, 6 + baseId + 1, state2 ? 127:0);
}
if (state3 != last_button_state[baseId + 2]) {
last_button_state[baseId + 2] = state3;
sendMessageNote(1, 6 + baseId + 2, state3 ? 127:0);
}
}
}
uint8_t putMatrixCol(uint8_t col) {
uint8_t fullByte = (1 << col);
digitalWrite(12, (col == 0));
digitalWrite(11, (col == 1));
digitalWrite(2, (col == 2));
digitalWrite(3, (col == 3));
digitalWrite(4, (col == 4));
digitalWrite(5, (col == 5));
digitalWrite(6, (col == 6));
digitalWrite(7, (col == 7));
return (PINB & 0b00000111);
}
void sendMessageNote(uint8_t channel, uint8_t note, int velocity) {
uint8_t statusByte = (velocity > 0 ? noteON : noteOFF) & 0xF0;
statusByte |= channel & 0x0F;
uart_putc(statusByte);
uart_putc(start_ch + note);
uart_putc(velocity);
}

View File

@@ -0,0 +1,56 @@
/*
Analog input, analog output, serial output
Reads an analog input pin, maps the result to a range from 0 to 255 and uses
the result to set the pulse width modulation (PWM) of an output pin.
Also prints the results to the Serial Monitor.
The circuit:
- potentiometer connected to analog pin 0.
Center pin of the potentiometer goes to the analog pin.
side pins of the potentiometer go to +5V and ground
- LED connected from digital pin 9 to ground through 220 ohm resistor
created 29 Dec. 2008
modified 9 Apr 2012
by Tom Igoe
This example code is in the public domain.
https://www.arduino.cc/en/Tutorial/BuiltInExamples/AnalogInOutSerial
*/
// These constants won't change. They're used to give names to the pins used:
const int analogInPin = A0; // Analog input pin that the potentiometer is attached to
const int analogOutPin = 9; // Analog output pin that the LED is attached to
int sensorValue = 0; // value read from the pot
int outputValue = 0; // value output to the PWM (analog out)
void setup() {
// initialize serial communications at 9600 bps:
Serial.begin(9600);
}
void loop() {
// print the results to the Serial Monitor:
Serial.print(readOne(A0));
Serial.print(",");
Serial.print(readOne(A1));
Serial.print(",");
Serial.print(readOne(A2));
Serial.print(",");
Serial.print(readOne(A3));
Serial.print(",");
Serial.println(readOne(A4));
// wait 2 milliseconds before the next loop for the analog-to-digital
// converter to settle after the last reading:
delay(2);
}
int readOne(int inputPin){
sensorValue = constrain(analogRead(inputPin),5,1020);
outputValue = map(sensorValue, 5, 1020, 127,0);
return outputValue;
}