Skip to content
Permalink
master
Go to file
 
 
Cannot retrieve contributors at this time
735 lines (586 sloc) 18.9 KB
/************************************************************************
version: default
*************************************************************************
adc - PORTF
io - PORTA
*/
#define F_CPU 16000000UL
#include <inttypes.h>
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <string.h>
#include "button.h"
#define SIZE_X 8
#define SIZE_Y 8
#define GRIDS 1
// firmware version: encoders
#define FW_VERSION 0
// protocol incoming
#define _SYS_QUERY 0x00
#define _SYS_QUERY_ID 0x01
#define _SYS_WRITE_ID 0x02
#define _SYS_GET_GRID_OFFSET 0x03
#define _SYS_SET_GRID_OFFSET 0x04
#define _SYS_GET_GRID_SIZE 0x05
#define _SYS_SET_GRID_SIZE 0x06
#define _SYS_SCAN_ADDR 0x07
#define _SYS_SET_ADDR 0x08
#define _SYS_QUERY_VERSION 0x0F
#define _LED_SET0 0x10
#define _LED_SET1 0x11
#define _LED_ALL0 0x12
#define _LED_ALL1 0x13
#define _LED_MAP 0x14
#define _LED_ROW 0x15
#define _LED_COL 0x16
#define _LED_INT 0x17
#define _LED_SETX 0x18
#define _LED_ALLX 0x19
#define _LED_MAPX 0x1A
#define _LED_ROWX 0x1B
#define _LED_COLX 0x1C
const uint8_t packet_length[32] = {
1,1,33,1, 4,1,3,1,3,0, 0,0,0,0,0,1,
3,3, 1,1,11,4,4,2,4,2,35,7,7,0,0,0
};
// protocol outgoing
#define _SYS_QUERY_RESPONSE 0x00
#define _SYS_ID 0x01
#define _SYS_REPORT_GRID_OFFSET 0x02
#define _SYS_REPORT_GRID_SIZE 0x03
#define _SYS_FOUND_ADDR 0x04
#define _SYS_REPORT_VERSION 0x05
// led pins
#define E0_CLK 0x01
#define E1_LD 0x02
#define E2_SER4 0x04
#define E3_SER3 0x08
#define E4_SER2 0x10
#define E5_SER1 0x20
#define ALL_SER 0x3C
// key in pins
#define E6_CLK 0x40
#define E7_LD 0x80
#define B0_SER4 0x01
#define B1_SER3 0x02
#define B2_SER2 0x04
#define B3_SER1 0x08
// key sel pins
#define B4_A0 0x10
#define B5_A1 0x20
#define B6_A2 0x40
// usb pins
#define C0_TXE 0x01
#define C1_RXF 0x02
#define C2_WR 0x04
#define C3_RD 0x08
#define C4_PWREN 0x10
#define B7_USB 0x80
// tuning
#define OUTPUT_BUFFER_LENGTH 256
#define KEY_REFRESH_RATE 2
#define RX_STARVE 20
static const uint8_t rev[] =
{
0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
};
// globals
volatile uint8_t port_enable;
volatile uint8_t scan_keypads;
// send packet to all led drivers
// ===============================================================
void to_all_led(char data1, char data2)
{
uint8_t i;
PORTE &= ~(E1_LD);
for(i=0;i<8;i++) {
if(data1 & (1<<(7-i)))
PORTE |= ALL_SER;
else
PORTE &= ~(ALL_SER);
PORTE |= (E0_CLK);
PORTE &= ~(E0_CLK);
}
for(i=0;i<8;i++) {
if(data2 & (1<<(7-i)))
PORTE |= ALL_SER;
else
PORTE &= ~(ALL_SER);
PORTE |= (E0_CLK);
PORTE &= ~(E0_CLK);
}
PORTE |= (E1_LD);
}
// update led drivers-- first byte to all, individual second bytes
// ===============================================================
void to_led(char data_all, char data1, char data2, char data3, char data4)
{
uint8_t i;
PORTE &= ~(E1_LD);
for(i=0;i<8;i++) {
if(data_all & (1<<(7-i)))
PORTE |= ALL_SER;
else
PORTE &= ~(ALL_SER);
PORTE |= (E0_CLK);
PORTE &= ~(E0_CLK);
}
for(i=0;i<8;i++) {
if(data1 & (1<<(7-i))) PORTE |= (E5_SER1);
else PORTE &= ~(E5_SER1);
if(data2 & (1<<(7-i))) PORTE |= (E4_SER2);
else PORTE &= ~(E4_SER2);
if(data3 & (1<<(7-i))) PORTE |= (E3_SER3);
else PORTE &= ~(E3_SER3);
if(data4 & (1<<(7-i))) PORTE |= (E2_SER4);
else PORTE &= ~(E2_SER4);
PORTE |= (E0_CLK);
PORTE &= ~(E0_CLK);
}
PORTE |= (E1_LD);
}
// KEYPAD SCAN INT
// ===============================================================
// ===============================================================
ISR(TIMER0_COMP_vect)
{
scan_keypads = 1;
TCNT0 = 0;
}
// main
// ===============================================================
// ===============================================================
// ===============================================================
int main(void)
{
uint8_t i1,i2,i3,i4;
uint8_t rx_count;
uint8_t rx_length = 100;
uint8_t rx_type;
uint8_t rx_timeout;
uint8_t rx[66]; // input buffer
uint8_t update_display;
uint8_t display[4][8];
char id[64];
uint8_t keypad_row;
uint8_t output_buffer[OUTPUT_BUFFER_LENGTH];
uint8_t output_write = 0;
// pin assignments
DDRE = 0xff; // all output
DDRB = B4_A0 | B5_A1 | B6_A2;
DDRC = C2_WR | C3_RD;
DDRD = 0;
PORTE = 0;
PORTB = 0;
PORTD = 0;
// aux pin assignments (encoders)
DDRA = 0;
DDRF = 0;
PORTA = 0xff; // activate internal pullups
PORTF = 0xff;
for(i1=0;i1<32;i1++) id[i1]=0;
strcpy(id,"mk");
// init led drivers
to_all_led(11, 7); // set scan limit to full range
to_all_led(10, 15); // set to max intensity
for(i1 = 1; i1 < 9; i1++) to_all_led(i1, 0); // clear pattern
to_all_led(12, 1); // come out of shutdown mode
to_all_led(15, 0); // test mode off
// startup sequence
to_led(8,12,0,0,0);
_delay_ms(64);
to_all_led(10, 13);
to_led(8,18,0,0,0); to_led(7,12,0,0,0);
_delay_ms(64);
to_all_led(10, 11);
to_led(8,33,0,0,0); to_led(7,18,0,0,0); to_led(6,12,0,0,0);
_delay_ms(64);
// to_all_led(10, 9);
// to_led(8,64,0,0,0); to_led(7,64,0,0,0); to_led(6,33,0,0,0); to_led(5,30,0,0,0);
// _delay_ms(64);
// to_all_led(10, 7);
// to_led(8,0,0,1,0); to_led(7,0,0,1,0); to_led(6,0,0,1,0); to_led(5,128,0,0,0); to_led(4,64,0,0,0); to_led(3,33,0,0,0); to_led(2,30,0,0,0);
// _delay_ms(64);
// to_all_led(10, 5);
// to_led(8,0,192,16,0); to_led(7,0,56,16,0); to_led(6,0,7,8,0); to_led(5,0,0,8,0); to_led(4,0,0,4,0); to_led(3,0,0,4,0); to_led(2,0,0,2,0); to_led(1,0,0,1,0);
// _delay_ms(64);
// to_all_led(10, 3);
// to_led(8,0,0,128,32); to_led(7,0,0,128,16); to_led(6,0,0,128,16); to_led(5,0,0,128,8); to_led(4,0,0,64,6); to_led(3,0,128,64,1); to_led(2,0,112,64,0); to_led(1,0,15,32,0);
// _delay_ms(64);
// to_all_led(10, 1);
// to_led(8,0,0,0,0); to_led(7,0,0,0,0); to_led(6,0,0,0,0); to_led(5,0,0,0,0); to_led(4,0,0,0,128); to_led(3,0,0,0,128); to_led(2,0,0,0,64); to_led(1,0,0,0,48);
// _delay_ms(64);
// end startup sequence
for(i1 = 1; i1 < 9; i1++) to_all_led(i1, 0); // clear pattern
to_all_led(10, 15); // set to max intensity
// init data
for(i1=0;i1<10;i1++) rx[i1] = 0;
for(i1=0;i1<4;i1++)
for(i2=0;i2<8;i2++)
display[i1][i2] = 0;
i1 = i2 = i3 = i4 = 0;
rx_count = rx_type = rx_timeout = 0;
rx_length = 100;
update_display=0;
keypad_row = 0;
output_write = 0;
buttonInit();
// keypad timer init
TCCR0A |= (1<<CS02);// | (1<<CS00); // timer0 on, prescale clk/1024 (p95)
TIMSK0 |= (1 << OCIE0A);// | (1<< TOIE0); // enable timer0 interrupts
OCR0A = KEY_REFRESH_RATE;
// enable ints
sei();
// main loop
while(1) {
// ========================= ASLEEP:
// if(sleep_state) {
// if(!(PINC & C4_PWREN)) {
// sleep_state = 0;
// to_all_led(12, 1); // out of shutdown
// for(i1=0;i1<64;i1++) { // fade in
// to_all_led(10, (i1)/4);
// _delay_ms(8);
// }
// }
// _delay_ms(255);
// TIMSK0 |= (1 << OCIE0A);// | (1<< TOIE0); // enable timer0 interrupts
// }
// ========================== NORMAL:
if(1) {
// ====================== check/read incoming serial
PORTD = 0; // setup PORTD for input
DDRD = 0; // input w/ tristate
while((PINC & C1_RXF) == 0) {
PORTC &= ~(C3_RD);
_delay_us(1); // wait for valid data
rx[rx_count] = PIND;
PORTC |= C3_RD;
if(rx_count == 0) { // get packet length if reading first byte
if(rx[0]<32) {
rx_type = rx[0];
if(packet_length[rx_type]) {
rx_length = packet_length[rx_type];
rx_count++;
rx_timeout = 0;
}
}
}
else rx_count++;
if(rx_count == rx_length) {
rx_count = 0;
if(rx_type == _SYS_QUERY) {
output_buffer[output_write] = _SYS_QUERY_RESPONSE;
output_write++;
output_buffer[output_write] = 1;
output_write++;
output_buffer[output_write] = GRIDS;
output_write++;
output_buffer[output_write] = _SYS_QUERY_RESPONSE;
output_write++;
output_buffer[output_write] = 2;
output_write++;
output_buffer[output_write] = GRIDS;
output_write++;
// ok = 1;
}
else if(rx_type == _SYS_QUERY_ID) {
output_buffer[output_write] = _SYS_ID;
output_write++;
for(i1=0;i1<32;i1++) {
output_buffer[output_write] = id[i1];
output_write++;
}
}
else if(rx_type == _SYS_GET_GRID_SIZE) {
output_buffer[output_write] = _SYS_REPORT_GRID_SIZE;
output_write++;
output_buffer[output_write] = SIZE_X;
output_write++;
output_buffer[output_write] = SIZE_Y;
output_write++;
}
else if(rx_type == _LED_SET0) {
// _LED_SET0 //////////////////////////////////////////////
i1 = (rx[1] >> 3) + ((rx[2] >> 3)*2);
i2 = 7-(rx[1] & 0x07);
i3 = rx[2] & 0x07;
display[i1][i2] &= ~(1<<i3);
update_display++;
}
else if(rx_type == _LED_SET1) {
// _LED_SET1 //////////////////////////////////////////////
i1 = (rx[1] >> 3) + ((rx[2] >> 3)*2);
i2 = 7-(rx[1] & 0x07);
i3 = rx[2] & 0x07;
display[i1][i2] |= (1<<i3);
update_display++;
} else if(rx_type == _LED_ALL0) {
// _LED_ALL0 //////////////////////////////////////////////
for(i1=0;i1<4;i1++) {
for(i2=0;i2<8;i2++) {
display[i1][i2] = 0;
}
}
update_display++;
} else if(rx_type == _LED_ALL1) {
// _LED_ALL1 //////////////////////////////////////////////
for(i1=0;i1<4;i1++) {
for(i2=0;i2<8;i2++) {
display[i1][i2] = 255;
}
}
update_display++;
} else if(rx_type == _LED_MAP) {
// _LED_MAP ///////////////////////////////////////////////
i1 = (rx[1] >> 3) + (rx[2] >> 3)*2;
for(i2=0;i2<8;i2++) {
i4 = 1 << i2;
for(i3=0;i3<8;i3++) {
if(rev[rx[i2+3]] & (1 << i3)) display[i1][i3] |= i4;
else display[i1][i3] &= ~i4;
}
}
update_display++;
} else if(rx_type == _LED_COL) {
// _LED_COL ///////////////////////////////////////////////
// x offset is rx[1]
i1 = (rx[1] >> 3) + (rx[2] >> 3)*2;
display[i1][7-(rx[1] & 0x07)] = rx[3];
update_display++;
} else if(rx_type == _LED_ROW) {
// _LED_ROW ///////////////////////////////////////////////
// y offset is rx[2]
i1 = (rx[1] >> 3) + (rx[2] >> 3)*2;
i2 = 1 << (rx[2] & 0x07);
for(i3=0;i3<8;i3++) {
i4 = 1 << i3;
if(rev[rx[3]] & i4) display[i1][i3] |= i2;
else display[i1][i3] &= ~i2;
}
update_display++;
} else if(rx_type == _LED_INT) {
// _LED_INT ///////////////////////////////////////////////
i1 = rx[1] & 0x0f;
to_all_led(10,i1);
} else if(rx_type == _LED_MAPX) {
i1 = (rx[1] >> 3) + (rx[2] >> 3)*2;
for(i2=0;i2<8;i2++) {
i4 = 1 << i2;
for(i3=0;i3<4;i3++) {
if((rx[3+(i2*4)+i3] >> 4) > 7) display[i1][7-(i3*2)] |= i4;
else display[i1][7-(i3*2)] &= ~i4;
if((rx[3+(i2*4)+i3] & 0xf) > 7) display[i1][7-(i3*2+1)] |= i4;
else display[i1][7-(i3*2+1)] &= ~i4;
}
}
update_display++;
} else if(rx_type == _LED_ALLX) {
// _LED_ALLX //////////////////////////////////////////////
i2 = (rx[1] > 7) * 255;
for(i3=0;i3<4;i3++)
for(i1=0;i1<8;i1++)
display[i3][i1]=i2;
update_display++;
} else if(rx_type == _LED_SETX) {
// _LED_SETX //////////////////////////////////////////////
i1 = (rx[1] >> 3) + ((rx[2] >> 3)*2);
i2 = 7-(rx[1] & 0x07);
i3 = rx[3] > 7;
if(i3)
display[i1][i2] |= (1<<(rx[2] & 0x07));
else
display[i1][i2] &= ~(1<<(rx[2] & 0x07));
update_display++;
} else if(rx_type == _LED_ROWX) {
// _LED_ROW ///////////////////////////////////////////////
// y offset is rx[2]
i1 = (rx[1] >> 3) + (rx[2] >> 3)*2;
i2 = 1 << (rx[2] & 0x07);
for(i3=0;i3<4;i3++) {
if((rx[3+i3] >> 4)> 7) display[i1][7-(i3*2)] |= i2;
else display[i1][7-(i3*2)] &= ~i2;
if((rx[3+i3] & 0xf) > 7) display[i1][7-(i3*2+1)] |= i2;
else display[i1][7-(i3*2+1)] &= ~i2;
}
update_display++;
} else if(rx_type == _LED_COLX) {
// _LED_COL ///////////////////////////////////////////////
// x offset is rx[1]
i1 = (rx[1] >> 3) + (rx[2] >> 3)*2;
for(i2=0;i2<4;i2++) {
if((rx[3+i2] >> 4) > 7)
display[i1][7-(rx[1] & 0x07)] |= 1 << (i2*2);
else
display[i1][7-(rx[1] & 0x07)] &= ~(1 << (i2*2));
if((rx[3+i2] & 0xf) > 7)
display[i1][7-(rx[1] & 0x07)] |= 1 << (i2*2+1);
else
display[i1][7-(rx[1] & 0x07)] &= ~(1 << (i2*2+1));
}
update_display++;
}
}
}
// ====================== scan keypads =========================================
if(scan_keypads) {
scan_keypads = 0;
PORTD = 0; // setup PORTD for output
DDRD = 0xFF;
button_last[keypad_row] = button_current[keypad_row];
button_last[keypad_row+8] = button_current[keypad_row+8];
button_last[keypad_row+16] = button_current[keypad_row+16];
button_last[keypad_row+24] = button_current[keypad_row+24];
_delay_us(4); // wait for voltage fall! due to high resistance pullup
PORTE |= (E7_LD);
_delay_us(2);
for(i2=0;i2<8;i2++) {
// =================================================
if(GRIDS > 0) {
i4 = (PINB & B3_SER1)!=0;
if (!i4)
button_current[keypad_row] |= (1 << i2);
else
button_current[keypad_row] &= ~(1 << i2);
buttonCheck(keypad_row, i2);
if (button_event[keypad_row] & (1 << i2)) {
button_event[keypad_row] &= ~(1 << i2);
output_buffer[output_write] = !i4 + 32;
output_write++;
output_buffer[output_write] = 7-keypad_row;
output_write++;
output_buffer[output_write] = i2;
output_write++;
}
}
// =================================================
if(GRIDS > 1) {
i3 = keypad_row + 8;
i4 = (PINB & B2_SER2)!=0;
if (!i4)
button_current[i3] |= (1 << i2);
else
button_current[i3] &= ~(1 << i2);
buttonCheck(i3, i2);
if (button_event[i3] & (1 << i2)) {
button_event[i3] &= ~(1 << i2);
output_buffer[output_write] = !i4 + 32;
output_write++;
output_buffer[output_write] = 15-keypad_row;
output_write++;
output_buffer[output_write] = i2;
output_write++;
// PORTC |= C2_WR;
// PORTD = i4 << 4;
// PORTC &= ~(C2_WR);
// PORTC |= C2_WR;
// PORTD = ((15-i1)<<4) | i2;
// PORTC &= ~(C2_WR);
}
}
// =================================================
if(GRIDS > 2) {
i3 = keypad_row + 16;
i4 = (PINB & B1_SER3)!=0;
if (!i4)
button_current[i3] |= (1 << i2);
else
button_current[i3] &= ~(1 << i2);
buttonCheck(i3, i2);
if (button_event[i3] & (1 << i2)) {
button_event[i3] &= ~(1 << i2);
output_buffer[output_write] = !i4 + 32;
output_write++;
output_buffer[output_write] = 7-keypad_row;
output_write++;
output_buffer[output_write] = i2 + 8;
output_write++;
// PORTC |= C2_WR;
// PORTD = i4 << 4;
// PORTC &= ~(C2_WR);
// PORTC |= C2_WR;
// PORTD = ((7-i1)<<4) | (i2+8);
// PORTC &= ~(C2_WR);
}
}
// =================================================
if(GRIDS > 3) {
i3 = keypad_row + 24;
i4 = (PINB & B0_SER4)!=0;
if (!i4)
button_current[i3] |= (1 << i2);
else
button_current[i3] &= ~(1 << i2);
buttonCheck(i3, i2);
if (button_event[i3] & (1 << i2)) {
button_event[i3] &= ~(1 << i2);
output_buffer[output_write] = !i4 + 32;
output_write++;
output_buffer[output_write] = 15-keypad_row;
output_write++;
output_buffer[output_write] = i2 + 8;
output_write++;
// PORTC |= C2_WR;
// PORTD = i4 << 4;
// PORTC &= ~(C2_WR);
// PORTC |= C2_WR;
// PORTD = ((15-i1)<<4) | (i2+8);
// PORTC &= ~(C2_WR);
}
}
PORTE |= (E6_CLK);
PORTE &= ~(E6_CLK);
}
PORTE &= ~(E7_LD);
keypad_row++;
keypad_row %= 8;
PORTB = keypad_row << 4;
}
// ====================== check/send output data
if(output_write) {
PORTD = 0; // setup PORTD for output
DDRD = 0xFF;
for(i1=0;i1<output_write;i1++) {
PORTC |= C2_WR;
PORTD = output_buffer[i1];
PORTC &= ~(C2_WR);
}
output_write = 0;
}
if(update_display) {
update_display = 0;
for(i1=0;i1<8;i1++) {
to_led(i1+1,display[0][i1],display[1][i1],display[2][i1],display[3][i1]);
}
}
// // ====================== check usb/sleep status
// if(PINC & C4_PWREN) {
// sleep_state = 1;
// TIMSK0 = 0; // turn off keypad checking int
// for(i1=0;i1<16;i1++) { // fade out
// to_all_led(10, 15-i1);
// _delay_ms(64);
// }
// to_all_led(12, 0); // shutdown
// }
}
}
return 0;
}