220 lines
4.8 KiB
C++
220 lines
4.8 KiB
C++
#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);
|
|
}
|