248 lines
7.3 KiB
C
248 lines
7.3 KiB
C
/*****************************************************************************
|
|
* MIDI Footswitch *
|
|
* Copyright (C) 2014-2018 Stefan Kalscheuer *
|
|
* *
|
|
* This program is free software: you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation version 3. *
|
|
* *
|
|
* This program 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 General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
|
*****************************************************************************/
|
|
|
|
/**
|
|
* MIDI Footswitch
|
|
*
|
|
* @file midifs.c
|
|
* @author Stefan Kalscheuer
|
|
* @date 2014-06-17
|
|
* @brief Main program
|
|
*
|
|
* Platform: ATtiny2313
|
|
* Internal RC-oscillator 8 MHz
|
|
*/
|
|
|
|
#define F_CPU 8000000UL
|
|
|
|
#include <avr/io.h>
|
|
#include <util/delay.h>
|
|
#include <avr/interrupt.h>
|
|
#include "midifs.h"
|
|
#include "usart.h"
|
|
|
|
// Counter for debouncing inputs.
|
|
volatile uint16_t counterBtn1 = 0;
|
|
volatile uint16_t counterBtn2 = 0;
|
|
volatile uint16_t counterBtn3 = 0;
|
|
volatile uint16_t counterBtn4 = 0;
|
|
volatile uint16_t counterSw1 = 0;
|
|
volatile uint16_t counterSw2 = 0;
|
|
|
|
// Input states.
|
|
volatile uint8_t stateBtn1 = 0;
|
|
volatile uint8_t stateBtn2 = 0;
|
|
volatile uint8_t stateBtn3 = 0;
|
|
volatile uint8_t stateBtn4 = 0;
|
|
volatile uint8_t stateSw1 = 0;
|
|
volatile uint8_t stateSw2 = 0;
|
|
|
|
// Channel, bank and tuner states.
|
|
volatile uint8_t currentChannel = 0;
|
|
volatile uint8_t currentBank = 0;
|
|
volatile uint8_t currentTuner = 0;
|
|
|
|
// Global interrupt counter.
|
|
uint16_t cnt = 0;
|
|
|
|
/**
|
|
* Switch to given bank.
|
|
*
|
|
* @param bank Bank number (supported 1 and 2).
|
|
* @return void
|
|
*/
|
|
void setBank(uint8_t bank) {
|
|
if (bank == 0) {
|
|
USART_Transmit(0xB0); // Bank 1
|
|
USART_Transmit(0x00);
|
|
USART_Transmit(0x00);
|
|
USART_Transmit(0xC0);
|
|
USART_Transmit(0x00);
|
|
USART_Transmit(currentChannel);
|
|
OUT_LED &= ~(1 << LED_RT); // LED green
|
|
OUT_LED |= (1 << LED_GN);
|
|
} else {
|
|
USART_Transmit(0xB0); // Bank 2
|
|
USART_Transmit(0x00);
|
|
USART_Transmit(0x01);
|
|
USART_Transmit(0xC0);
|
|
USART_Transmit(0x00);
|
|
USART_Transmit(currentChannel);
|
|
OUT_LED &= ~(1 << LED_GN); // LED green
|
|
OUT_LED |= (1 << LED_RT);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Main routine.
|
|
*
|
|
* @return This method should never terminate.
|
|
*/
|
|
int main(void) {
|
|
DDRB = 0x00; // PB1..7 as inputs
|
|
PORTB = 0xFF; // interlan pull-ups for PB0..7y
|
|
DDRD = 0x30; // PD4..5 as outputs
|
|
PORTD = 0x0C; // internal pull-ups for PD2..3
|
|
|
|
OUT_LED = 0x30; // LEDs off
|
|
|
|
// Timer1 init
|
|
TCCR1A |= (1 << WGM01); // Set timer 0 to CTC-Mode
|
|
TCCR1B &= ~(1 << CS10); // Prescaler 8 (1MHz)
|
|
TCCR1B |= (1 << CS11);
|
|
TCCR1B &= ~(1 << CS12);
|
|
OCR1A = 499; // Pperiod of 1 ms
|
|
|
|
cli(); // Disable interrupts
|
|
TIMSK |= (1 << TOIE1); // Activate timer 1
|
|
sei(); // Enable interrupts
|
|
|
|
//USART_Init(38400); // Initialize USART with 38400 baud (debug)
|
|
USART_Init(31250); // Initialize USART with 31250 baud
|
|
|
|
while (1) {
|
|
if (counterBtn1 > BTN_THRESHOLD && stateBtn1 == 0) { // Button 1
|
|
setBank(currentBank);
|
|
USART_Transmit(0xC0); // Channel 1
|
|
USART_Transmit(0x00);
|
|
|
|
currentChannel = 0;
|
|
currentTuner = 0;
|
|
|
|
stateBtn1 = 1;
|
|
} else if (counterBtn1 < BTN_THRESHOLD && stateBtn1 == 1) {
|
|
stateBtn1 = 0;
|
|
}
|
|
|
|
if (counterBtn2 > BTN_THRESHOLD && stateBtn2 == 0) { // Button 2
|
|
setBank(currentBank);
|
|
USART_Transmit(0xC0); // Channel 2
|
|
USART_Transmit(0x01);
|
|
currentChannel = 1;
|
|
currentTuner = 0;
|
|
|
|
stateBtn2 = 1;
|
|
} else if (counterBtn2 < BTN_THRESHOLD && stateBtn2 == 1) {
|
|
stateBtn2 = 0;
|
|
}
|
|
|
|
if (counterBtn3 > BTN_THRESHOLD && stateBtn3 == 0) { // Button 3
|
|
setBank(currentBank);
|
|
USART_Transmit(0xC0); // Channel 3
|
|
USART_Transmit(0x02);
|
|
currentChannel = 2;
|
|
currentTuner = 0;
|
|
|
|
stateBtn3 = 1;
|
|
} else if (counterBtn3 < BTN_THRESHOLD && stateBtn3 == 1) {
|
|
stateBtn3 = 0;
|
|
}
|
|
|
|
if (counterBtn4 > BTN_THRESHOLD && stateBtn4 == 0) { // Button 4
|
|
USART_Transmit(0xB0); // Tuner on
|
|
USART_Transmit(0x0F);
|
|
USART_Transmit(0x7F);
|
|
|
|
//OUT_LED |= (1 << LED_RT); // LEDs off
|
|
//OUT_LED |= (1 << LED_GN);
|
|
|
|
currentTuner = 1;
|
|
|
|
stateBtn4 = 1;
|
|
} else if (counterBtn4 < BTN_THRESHOLD && stateBtn4 == 1) {
|
|
stateBtn4 = 0;
|
|
}
|
|
|
|
if (counterSw1 > BTN_THRESHOLD && stateSw1 == 0) { // Switch Pos. 1
|
|
setBank(0);
|
|
currentBank = 0;
|
|
currentTuner = 0;
|
|
|
|
stateSw1 = 1;
|
|
} else if (counterSw1 < BTN_THRESHOLD && stateSw1 == 1) {
|
|
stateSw1 = 0;
|
|
}
|
|
|
|
if (counterSw2 > BTN_THRESHOLD && stateSw2 == 0) { // Switch Pos. 2
|
|
setBank(1);
|
|
currentBank = 1;
|
|
currentTuner = 0;
|
|
|
|
stateSw2 = 1;
|
|
} else if (counterSw2 < BTN_THRESHOLD && stateSw2 == 1) {
|
|
stateSw2 = 0;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/**
|
|
* interrupt function: TIMER1_OVF1_vect
|
|
*
|
|
* Timer interrupt. Increments counters for inputs
|
|
*/
|
|
ISR(TIMER1_OVF_vect) {
|
|
if (++cnt == 250) {
|
|
cnt = 0;
|
|
}
|
|
|
|
if (currentTuner == 1 && cnt == 1) {
|
|
if (currentBank == 1) {
|
|
OUT_LED ^= (1 << LED_GN);
|
|
} else {
|
|
OUT_LED ^= (1 << LED_RT);
|
|
}
|
|
}
|
|
|
|
if (bit_is_clear(IN_BTN, BTN1) && counterBtn1 < BTN_MAX) { // Button 1
|
|
counterBtn1++;
|
|
} else if (counterBtn1 > 0) {
|
|
counterBtn1--;
|
|
}
|
|
|
|
if (bit_is_clear(IN_BTN, BTN2) && counterBtn2 < BTN_MAX) { // Button 2
|
|
counterBtn2++;
|
|
} else if (counterBtn2 > 0) {
|
|
counterBtn2--;
|
|
}
|
|
|
|
|
|
if (bit_is_clear(IN_BTN, BTN3) && counterBtn3 < BTN_MAX) { // Button 3
|
|
counterBtn3++;
|
|
} else if (counterBtn3 > 0) {
|
|
counterBtn3--;
|
|
}
|
|
|
|
if (bit_is_clear(IN_BTN, BTN4) && counterBtn4 < BTN_MAX) { // Button 4
|
|
counterBtn4++;
|
|
} else if (counterBtn4 > 0) {
|
|
counterBtn4--;
|
|
}
|
|
|
|
if (bit_is_clear(IN_SW, SW1) && counterSw1 < BTN_MAX) { // Switch 1
|
|
counterSw1++;
|
|
} else if (counterSw1 > 0) {
|
|
counterSw1--;
|
|
}
|
|
|
|
if (bit_is_clear(IN_SW, SW2) && counterSw2 < BTN_MAX) { // Switch 2
|
|
counterSw2++;
|
|
} else if (counterSw2 > 0) {
|
|
counterSw2--;
|
|
}
|
|
}
|