/*
* Keybordscanner.c
*
* Created: 04.01.2019 20:00:53
* Author : USER
*/
#define F_CPU 20000000
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
//********* Testvariablen ***********
uint8_t senddata = 0;
//MiDi variables
#define noteon 0x90 //Note On Byte
#define noteoff 0x80 //Note Off Byte
#define bufferlengh 168 //Bufferlengh for MiDi messages
#define transpose 20 //Transpose of MiDi notes
uint8_t midibuffer [bufferlengh]; //Buffer for MiDi messages
uint8_t midiwrite = 0; //MiDi buffer writepointer
uint8_t midiread = 0; //MiDi buffer readpointer
//scan process variables
#define idle 0
#define notestart 1
#define midisent 2
volatile uint8_t nextscan = 0; //Next Keyboard scan started
//Velocity counter
uint8_t note_velocity [56] =
{
128,128,128,128,128,128,128,128,
128,128,128,128,128,128,128,128,
128,128,128,128,128,128,128,128,
128,128,128,128,128,128,128,128,
128,128,128,128,128,128,128,128,
128,128,128,128,128,128,128,128,
128,128,128,128,128,128,128,128
};
//State memory
uint8_t note_state [56] =
{
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0
};
//Scan process will start every 300µs
ISR (TIMER1_COMPA_vect)
{
nextscan++;
}
void scan_keyboard (void)
{
uint8_t buffer1 = 0, buffer2 = 0, zeiger = 0, scanloop = 0, i = 0;
/* Outer loop - Pulls down the lines after the diodes */
for(scanloop=0;scanloop<8;scanloop++)
{
buffer1 = PINA;
buffer2 = PINC;
PORTB = ~(1<<(scanloop+1));
//Inner loop readout start velocity and end velocity lines and generate MiDi messages
for(i=0;i<7;i++)
{
//Pointer to actual note
zeiger = i*8 + scanloop;
//Scan velocity start first sample
if((buffer1 & (1<<i)) == 0)
{
if(note_state[zeiger] == idle) //Velocity counting begins
{
note_state[zeiger] = notestart;
}
if(note_state[zeiger] == notestart)
{
if(note_velocity[zeiger] > 1) //Velocity counting go on
{
note_velocity[zeiger]--;
}
}
}
else
{
/*MiDi sent, back to idle or send note off
when key pressed a little and go back to off state
the mode go back to idle.
When a complete scan was processed a Note On velocity 0 was sent */
if(note_state[zeiger] == notestart)
{
note_state[zeiger] = idle;
note_velocity[zeiger] = 128;
}
if(note_state[zeiger] == midisent)
{
midibuffer[midiwrite] = noteon;
midiwrite++;
if(midiwrite>bufferlengh){ midiwrite=0; }
midibuffer[midiwrite]= zeiger+transpose;
midiwrite++;
if(midiwrite>bufferlengh){ midiwrite=0; }
midibuffer[midiwrite]= 0;
midiwrite++;
if(midiwrite>bufferlengh){ midiwrite=0; }
note_state[zeiger] = idle;
}
}
//Velocity Stop second sample generate MiDi
if((buffer2 & (1<<i)) == 0)
{
if(note_state[zeiger] != midisent)
{
midibuffer[midiwrite++] = noteon;
if(midiwrite>bufferlengh){ midiwrite=0; }
midibuffer[midiwrite++]= zeiger+transpose;
if(midiwrite>bufferlengh){ midiwrite=0; }
midibuffer[midiwrite++]= note_velocity[zeiger];
if(midiwrite>bufferlengh){ midiwrite=0; }
note_state[zeiger]=midisent;
note_velocity[zeiger] = 128;
}
}
}
}
}
int main(void)
{
// Declare your local variables here
// Input/Output Ports initialization
// Port A initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRA=(0<<DDA7) | (0<<DDA6) | (0<<DDA5) | (0<<DDA4) | (0<<DDA3) | (0<<DDA2) | (0<<DDA1) | (0<<DDA0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTA=(0<<PORTA7) | (0<<PORTA6) | (0<<PORTA5) | (0<<PORTA4) | (0<<PORTA3) | (0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0);
// Port B initialization
// Function: Bit7=Out Bit6=Out Bit5=Out Bit4=Out Bit3=Out Bit2=Out Bit1=Out Bit0=Out
DDRB=(1<<DDB7) | (1<<DDB6) | (1<<DDB5) | (1<<DDB4) | (1<<DDB3) | (1<<DDB2) | (1<<DDB1) | (1<<DDB0);
// State: Bit7=0 Bit6=0 Bit5=0 Bit4=0 Bit3=0 Bit2=0 Bit1=0 Bit0=0
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);
// Port C initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRC=(0<<DDC7) | (0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (0<<DDC3) | (0<<DDC2) | (0<<DDC1) | (0<<DDC0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTC=(0<<PORTC7) | (0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0);
// Port D initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=0xFF
// OC0 output: Disconnected
TCCR0=(0<<WGM00) | (0<<COM01) | (0<<COM00) | (0<<WGM01) | (0<<CS02) | (0<<CS01) | (0<<CS00);
TCNT0=0x00;
OCR0=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 2500,000 kHz
// Mode: Normal top=0xFFFF
// OC1A output: Clear on compare match
// OC1B output: Disconnected
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer Period: 26,214 ms
// Output Pulse(s):
// OC1A Period: 26,214 ms
// Timer1 Overflow Interrupt: On
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (1<<WGM12) | (0<<CS12) | (1<<CS11) | (0<<CS10);
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x02;
OCR1AL=0xEE; //was 0x7F
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=0xFF
// OC2 output: Disconnected
ASSR=0<<AS2;
TCCR2=(0<<FOC2) | (0<<COM21) | (0<<COM20) | (0<<WGM21) | (0<<CS22) | (0<<CS21) | (0<<CS20);
TCNT2=0x00;
OCR2=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (1<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (0<<OCIE0) | (0<<TOIE0);
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
MCUCSR=(0<<ISC2);
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: Off
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 31250
UCSRA=(0<<RXC) | (0<<TXC) | (0<<UDRE) | (0<<FE) | (0<<DOR) | (0<<UPE) | (0<<U2X) | (0<<MPCM);
UCSRB=(0<<RXCIE) | (0<<TXCIE) | (0<<UDRIE) | (0<<RXEN) | (1<<TXEN) | (0<<UCSZ2) | (0<<RXB8) | (0<<TXB8);
UCSRC=(1<<URSEL) | (0<<UMSEL) | (0<<UPM1) | (0<<UPM0) | (0<<USBS) | (1<<UCSZ1) | (1<<UCSZ0) | (0<<UCPOL);
UBRRH=0x00;
UBRRL=0x27;
// Analog Comparator initialization
// Analog Comparator: Off
// The Analog Comparator's positive input is
// connected to the AIN0 pin
// The Analog Comparator's negative input is
// connected to the AIN1 pin
ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIC) | (0<<ACIS1) | (0<<ACIS0);
SFIOR=(0<<ACME);
// ADC initialization
// ADC disabled
ADCSRA=(0<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (0<<ADPS2) | (0<<ADPS1) | (0<<ADPS0);
// SPI initialization
// SPI disabled
SPCR=(0<<SPIE) | (0<<SPE) | (0<<DORD) | (0<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0);
// TWI initialization
// TWI disabled
TWCR=(0<<TWEA) | (0<<TWSTA) | (0<<TWSTO) | (0<<TWEN) | (0<<TWIE);
// Globally enable interrupts
sei();
PORTB=0b11111110; //Prepare for first scan cycle
while (1)
{
if(nextscan > 0)
{
scan_keyboard();
nextscan=0;
PORTB = 0b11111110; //Prepare for next round
}
//send MiDi data out of the NiDi buffer
while((midiread != midiwrite)&&((UCSRA & (1<<UDRE))>0))
{
senddata = midibuffer[midiread];
UDR = midibuffer[midiread];
midiread++;
if(midiread>bufferlengh){midiread = 0;}
}
}
}