Rev 107 | Rev 109 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
/** atcpad.c** Created: 7/06/2013 10:15:34 PM* Author: pfowler*/#include <avr/io.h>#include <avr/pgmspace.h>#include <avr/interrupt.h>#include <util/delay.h>#include <avr/wdt.h>#include <stdlib.h>#include <string.h>#include "usbdrv.h"#include "atcpad.h"#include "avrutil.h"#include "lcd.h"#include "wire.h"#include "hiddesc.h"#define BUTTONS 1#define LCD_UPDATE 11#define ROTARY_ON_TIME 30#define ROTARY_OFF_TIME 15void pcInterrupt(uint8_t);uint8_t getKey(void);void updateLcd();void checkRotarys();void checkButtons(void);// * = 0x25, #=0x20, 0 = 0x27// F9 = 0x42, F12 = 0x45, ` = 0x35uint8_t keyMap[] = { 0x1E, 0x1F, 0x20, // 1, 2, 30x21, 0x22, 0x23, // 4, 5, 60x24, 0x25, 0x26, // 7, 8, 90x42, 0x35, 0x45 }; // F9, `, F12uint8_t lcdRectangle[] = {0B00011111,0B00010001,0B00010001,0B00010001,0B00010001,0B00010001,0B00010001,0B00011111 };uint8_t oldpotVal = 0;uint8_t keySelect = 1;// Start these of at different times, so they// don't kick of it the same loop runvolatile uint8_t lcdTimer = 8;volatile struct {uint8_t current;uint8_t last;uint8_t mask;} pcInt[3];volatile struct {uint8_t detected;uint8_t timer;uint8_t waitup;} buttons[BUTTONS];volatile struct {uint8_t direction;uint8_t timer;} rotary;int main(void) {setup();while(1){wdt_reset();loop();}}void setup() {/*DDR : 1 = Output, 0 = InputPORT: 1 = Pullup for Input, otherwise set outputPIN : Read input pin*//*PB0 - Output - Keypad 2PB1 - Output - Keypad 7PB2 - Output - Keypad 6PB3 - Output - Keypad 4PB4 - Input, Pullup - Function selectPB5 - Input, Pullup - Function select*/DDRB = 0B00001111;PORTB = 0B00111111;/*PD0 - Input, Pullup, PCINT16 - Rotary 1aPD1 - Input, Pullup, PCINT17 - Rotary 1bPD4 - Output - Keypad select status ledPD5 - Input, Pullup - Keypad 3PD6 - Input, Pullup - Keypad 1PD7 - Input, Pullup - Keypad 5*/DDRD = 0B00010000;PORTD = 0B11110011;PCMSK2 |= (( 1 << PCINT16 ) | ( 1 << PCINT17 )); //enable encoder pins interrupt sourcesPCICR |= ( 1 << PCIE2 ); //enable pin change interruptsanalogInit();sysclockInit();reportKeyboard.report_id = 1;reportJoystick.report_id = 2;usbDeviceDisconnect(); /* enforce re-enumeration, do this while interrupts are disabled! */_delay_ms(500);usbDeviceConnect();sei();wdt_enable(WDTO_1S);usbInit();i2c_master();lcd_init();lcd_createChar(0x00, lcdRectangle);char strTime[] = {'T', 'i', 'm', 'e', ':', 0x00};lcd_setCursor(0, 1);lcd_print(strTime);buttons[0].detected = 0;buttons[0].timer = 0;buttons[0].waitup = 0;cbi(PORTD, 4);}void loop() {usbPoll();if (lcdTimer==0) {updateLcd();lcdTimer = LCD_UPDATE;}reportJoystick.data1[0] = (-128 + analogRead(0));reportJoystick.data1[1] = (-128 + analogRead(1));reportJoystick.data2 = 0x0000; // Clear all the buttonsreportKeyboard.modifier = 0x00;reportKeyboard.keycode = 0x00;checkButtons();checkRotarys();if(usbInterruptIsReady()){usbSendHidReport((uchar*)&reportKeyboard, sizeof(reportKeyboard));usbSendHidReport((uchar*)&reportJoystick, sizeof(reportJoystick));}}uint8_t getKey() {uint8_t col, row = 0;uint8_t key = 0;uint8_t n = 1;for (row=0; row<=3; row++) {cbi(PORTB, row);_delay_us(10); // Wait for the port to changefor (col=5; col<=7; col++) {if (rbi(PIND, col) == 0)key = n;n++;}sbi(PORTB, row);}return key;}void checkRotarys() {if (rotary.direction && rotary.timer == 0) {rotary.direction = 0x00;rotary.timer = ROTARY_OFF_TIME;}if (rotary.timer == 0) {if (rotary.direction == 1) {reportJoystick.rot1a = 1;} else if (rotary.direction == 2) {reportJoystick.rot1b = 1;}}}void checkButtons() {uint8_t key = getKey();if (rbi(keySelect, 0)) {// Keypad is joystickif (key > 0)reportJoystick.data2 |= (1 << (--key));} else {// Keypad is keyboardif (key > 0) {//if (key==10 || key==12) // Left shift, for *, #// reportKeyboard.modifier |= (1<<1);reportKeyboard.keycode = keyMap[--key];}}// Only one button for nowif (rbi(PINB, 5) == 0 && buttons[0].detected == 0 && buttons[0].timer == 0) {buttons[0].detected = 1;buttons[0].timer = 5;buttons[0].waitup = 0;}if (rbi(PINB, 5) == 1 && buttons[0].waitup == 1) {buttons[0].detected = 0;buttons[0].timer = 0;buttons[0].waitup = 0;}if (buttons[0].detected == 1 && buttons[0].timer == 0 && buttons[0].waitup == 0 ) {xbi(keySelect, 0);if (keySelect == 0)sbi(PORTD, PD4);elsecbi(PORTD, PD4);buttons[0].waitup = 1;}}void updateLcd() {usbPoll();char syschar[10];ultoa(systime, syschar, 10);lcd_overprint_right(syschar, 10, 5, 1);uint8_t potVal = map_8(analogRead(0), 0, 255, 0, 100);if (potVal != oldpotVal) {lcd_percent_graph(potVal, 0, 0);oldpotVal = potVal;char pot[3];utoa(potVal, pot, 10);lcd_overprint_right(pot, 3, 11, 0);// Set percentagelcd_setCursor(15, 0);lcd_char(0x25);}}void millis_tick() {}/*** Process the Pin Change Interrupt.* pcint provides what bank caused the interrupt**/void pcInterrupt(uint8_t pcint) {switch (pcint) {case 0: pcInt[pcint].current = PINB; break;case 1: pcInt[pcint].current = PIND; break;case 2: pcInt[pcint].current = PINC; break;}pcInt[pcint].mask = pcInt[pcint].current ^ pcInt[pcint].last;pcInt[pcint].last = pcInt[pcint].current;// If rot stat is not 0, we havn't sent// our last results yet. Skip this click.if (rotary.direction != 0) {pcInt[pcint].mask = 0;return;}// Check which pin caused the interrupt. If they both// equal 0, the pin that interrupted is the directionif (rbi(pcInt[pcint].current, PCINT16) == 0&& rbi(pcInt[pcint].current, PCINT17) == 0&& rbi(pcInt[pcint].mask, PCINT16) ) {if (rotary.timer == 0) {rotary.direction = 1;rotary.timer = ROTARY_ON_TIME;}} else if (rbi(pcInt[pcint].current, PCINT16) == 0&& rbi(pcInt[pcint].current, PCINT17) == 0&& rbi(pcInt[pcint].mask, PCINT17) ) {if (rotary.timer == 0) {rotary.direction = 2;rotary.timer = ROTARY_ON_TIME;}}// Clear the mask so we know we've delth with itpcInt[pcint].mask = 0;}ISR(TIMER0_OVF_vect) {tmr0_ovf++;if (tmr0_ovf >= sys_ovf_tick) {systime++;tmr0_ovf = 0;//millis_tick(); // Not working, taking too long to call?if (buttons[0].timer)buttons[0].timer--;if (lcdTimer)lcdTimer--;if (rotary.timer)rotary.timer--;}}ISR(PCINT0_vect) {pcInterrupt(0);}ISR(PCINT1_vect) {pcInterrupt(1);}ISR(PCINT2_vect) {pcInterrupt(2);}void usbSendHidReport(uchar * data, uchar len) {while(1){usbPoll();if (usbInterruptIsReady()){usbSetInterrupt(data, len);break;}}}usbMsgLen_t usbFunctionSetup(uchar data[8]) {usbRequest_t *rq = (void *)data;if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) {switch (rq->bRequest) {case USBRQ_HID_GET_REPORT:if (rq->wValue.bytes[0] == 1)return sizeof(reportKeyboard);else if (rq->wValue.bytes[0] == 2)return sizeof(reportJoystick);elsereturn 0;case USBRQ_HID_GET_IDLE:usbMsgPtr = &idleRate;return 1;default:return 0;}}return 0;}void hadUsbReset(void) {}