/***************************************************************************** * 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 . * *****************************************************************************/ /** * 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 #include #include #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--; } }