Skip to content

Instantly share code, notes, and snippets.

@sash13
Created October 27, 2012 17:25
Show Gist options
  • Select an option

  • Save sash13/3965409 to your computer and use it in GitHub Desktop.

Select an option

Save sash13/3965409 to your computer and use it in GitHub Desktop.
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
//#include <avr/eeprom.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <string.h>
#include "usbdrv.h"
/*#define JOI2 PINB
#define D0 PB1
#define D1 PB2
#define D2 PB4
#define D3 PB3
#define D4 PB0
#define D5 PB5
#define SEL2 PD7
*/
#define JOI2 PINB
#define SEL2 PD7
#define JOI1 PINC
#define D0 PC1
#define D1 PC2
#define D2 PC3
#define D3 PC4
#define D4 PC0
#define D5 PC5
#define SEL1 PD6
#define KEY_A 4
#define KEY_B 5
#define KEY_C 6
#define KEY_D 7
#define KEY_E 8
#define KEY_F 9
#define KEY_G 10
#define KEY_H 11
#define KEY_I 12
#define KEY_J 13
#define KEY_K 14
#define KEY_L 15
#define KEY_M 16
#define KEY_N 17
#define KEY_O 18
#define KEY_P 19
#define KEY_Q 20
#define KEY_R 21
#define KEY_S 22
#define KEY_T 23
#define KEY_U 24
#define KEY_V 25
#define KEY_W 26
#define KEY_X 27
#define KEY_Y 28
#define KEY_Z 29
#define KEY_1 30
#define KEY_2 31
#define KEY_3 32
#define KEY_4 33
#define KEY_5 34
#define KEY_6 35
#define KEY_7 36
#define KEY_8 37
#define KEY_9 38
#define KEY_0 39
#define RightArrow 79
#define LeftArrow 80
#define DownArrow 81
#define UpArrow 82
#define ENTER 40
// ************************
// *** USB HID ROUTINES ***
// ************************
// From Frank Zhao's USB Business Card project
// http://www.frank-zhao.com/cache/usbbusinesscard_details.php
PROGMEM char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x05, 0x07, // USAGE_PAGE (Keyboard)(Key Codes)
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)(224)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)(231)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x81, 0x02, // INPUT (Data,Var,Abs) ; Modifier byte
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs) ; Reserved byte
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs) ; LED report
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x91, 0x03, // OUTPUT (Cnst,Var,Abs) ; LED report padding
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)(Key Codes)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))(0)
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)(101)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0 // END_COLLECTION
};
typedef struct {
uint8_t modifier;
uint8_t reserved;
uint8_t keycode[6];
} keyboard_report_t;
static uint8_t idle_rate = 500 / 4; // see HID1_11.pdf sect 7.2.4
static uint8_t protocol_version = 0; // see HID1_11.pdf sect 7.2.6
static keyboard_report_t keyboard_report; // sent to PC
static keyboard_report_t keyboard_report_1; // sent to PC2
static keyboard_report_t keyboard_report_old; // sent to PC
//volatile static uchar LED_state = 0xff; // received from PC
static uchar idleRate; // repeat rate for keyboards
//uchar keyDidChange=1;
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: // send "no keys pressed" if asked here
// wValue: ReportType (highbyte), ReportID (lowbyte)
usbMsgPtr = (void *)&keyboard_report; // we only have this one
keyboard_report.modifier = 0;
keyboard_report.keycode[0] = 0;
return sizeof(keyboard_report);
//case USBRQ_HID_SET_REPORT: // if wLength == 1, should be LED state
// return (rq->wLength.word == 1) ? USB_NO_MSG : 0;
case USBRQ_HID_GET_IDLE: // send idle rate to PC as required by spec
usbMsgPtr = &idleRate;
return 1;
case USBRQ_HID_SET_IDLE: // save idle rate as required by spec
idleRate = rq->wValue.bytes[1];
return 0;
}
}
return 0; // by default don't return any data
}
#define NUM_LOCK 1
#define CAPS_LOCK 2
#define SCROLL_LOCK 4
usbMsgLen_t usbFunctionWrite(uint8_t * data, uchar len) {
/*if (data[0] == LED_state)
return 1;
else
LED_state = data[0];
// LED state changed
if(LED_state & CAPS_LOCK)
PORTB |= 1 << PB1; // LED on
else
PORTB &= ~(1 << PB1); // LED off
*/
return 1; // Data read, not expecting more
}
static void hardwareInit(void)
{
uchar i, j;
PORTB = 0xff; /* activate all pull-ups */
DDRB = 0; /* all pins input */
PORTC = 0xff; /* activate all pull-ups */
DDRC = 0; /* all pins input */
//PORTD = 0xfc; /* 1111 1100 bin: activate pull-ups except on USB lines */
DDRD = 1 << PD7; // select joi 1
DDRD = 1 << PD6; // select joi 2
PORTD |= 1 << SEL1;
PORTD |= 1 << SEL2;
}
/*void usbSendHidReport(uchar * data, uchar len)
{
while(1)
{
usbPoll();
if (usbInterruptIsReady())
{
buildReport('x');
usbSetInterrupt(data, len);
break;
}
}
}*/
/*static uchar keyPressed(void)
{
if(!(PINB & (1<<PB0))) {
return 'a';
}
return '0';
}*/
static void keyPressed(void)
{
uchar i, mask, x, standart[6], low_select[6], pulse_select[6], standart1[6], low_select1[6], pulse_select1[6];
PORTD |= 1 << SEL1;
//PORTD |= 1 << SEL2;
for(i=0; i<sizeof(keyboard_report); i++) // clear report initially
((uchar *)&keyboard_report)[i] = 0;
for(i=0; i<sizeof(keyboard_report_1); i++) // clear report initially
((uchar *)&keyboard_report_1)[i] = 0;
/*if(!(JOI2 & (1<<D4))) {
keyboard_report.keycode[0] = KEY_B;
}
if(!(JOI2 & (1<<D5))) {
keyboard_report.keycode[1] = KEY_C;
}
if(!(JOI2 & (1<<D0))) {
keyboard_report.keycode[2] = UpArrow;
}
if(!(JOI2 & (1<<D1))) {
keyboard_report.keycode[2] = DownArrow;
}
if(!(JOI2 & (1<<D2))) {
keyboard_report.keycode[3] = LeftArrow;
}
if(!(JOI2 & (1<<D3))) {
keyboard_report.keycode[3] = RightArrow;
}
// Low Select
PORTD &= ~(1 << SEL2);
_delay_ms(10);
if(!(JOI2 & (1<<D4))) {
keyboard_report.keycode[4] = KEY_A;
}
if(!(JOI2 & (1<<D5))) {
keyboard_report.keycode[5] = ENTER;
}*/
/*if(!(JOI1 & (1<<D4))) {
keyboard_report.keycode[0] = KEY_B;
}
if(!(JOI1 & (1<<D5))) {
keyboard_report.keycode[1] = KEY_C;
}
if(!(JOI1 & (1<<D0))) {
keyboard_report.keycode[2] = UpArrow;
}
if(!(JOI1 & (1<<D1))) {
keyboard_report.keycode[2] = DownArrow;
}
if(!(JOI1 & (1<<D2))) {
keyboard_report.keycode[3] = LeftArrow;
}
if(!(JOI1 & (1<<D3))) {
keyboard_report.keycode[3] = RightArrow;
}*/
//x = JOI1;
//JOI1////////////////////////////////////////////////////////////////////////////////////////
mask = 1;
for(i=0;i<6;i++){
if(!(JOI1 & mask))
standart[i]=1;
else
standart[i]=0;
mask <<= 1;
}
/*mask = 1;
for(i=0;i<6;i++){
if(!(JOI2 & mask))
standart1[i]=1;
else
standart1[i]=0;
mask <<= 1;
}*/
// Low Select
//PORTD &= ~(1 << SEL2);
PORTD &= ~(1 << SEL1);
_delay_us(10);
mask = 1;
for(i=0;i<6;i++){
if(!(JOI1 & mask))
low_select[i]=1;
else
low_select[i]=0;
mask <<= 1;
}
/*mask = 1;
for(i=0;i<6;i++){
if(!(JOI2 & mask))
low_select1[i]=1;
else
low_select1[i]=0;
mask <<= 1;
}*/
//PORTD |= 1 << SEL2;
PORTD |= 1 << SEL1;
_delay_us(10);
//pULSE MODE
PORTD &= ~(1 << SEL1);
//PORTD &= ~(1 << SEL2);
_delay_us(300);
PORTD |= 1 << SEL1;
//PORTD |= 1 << SEL2;
_delay_us(300);
PORTD &= ~(1 << SEL1);
//PORTD &= ~(1 << SEL2);
_delay_us(300);
PORTD |= 1 << SEL1;
//PORTD |= 1 << SEL2;
_delay_us(300);
mask = 1;
for(i=0;i<6;i++){
if(!(JOI1 & mask))
pulse_select[i]=1;
else
pulse_select[i]=0;
mask <<= 1;
}
mask = 1;
/*for(i=0;i<6;i++){
if(!(JOI2 & mask))
pulse_select1[i]=1;
else
pulse_select1[i]=0;
mask <<= 1;
}*/
PORTD &= ~(1 << SEL1);
//PORTD &= ~(1 << SEL2);
_delay_us(300);
PORTD |= 1 << SEL1;
//PORTD |= 1 << SEL2;
_delay_us(300);
//JOI2////////////////////////////////////////////////////////////////////////////////////////
/*mask = 1;
for(i=0;i<6;i++){
if(!(JOI2 & mask))
standart1[i]=1;
else
standart1[i]=0;
mask <<= 1;
}
// Low Select
PORTD &= ~(1 << SEL2);
_delay_us(10);
mask = 1;
for(i=0;i<6;i++){
if(!(JOI2 & mask))
low_select1[i]=1;
else
low_select1[i]=0;
mask <<= 1;
}
PORTD |= 1 << SEL2;
_delay_us(10);
//pULSE MODE
PORTD &= ~(1 << SEL2);
_delay_us(300);
PORTD |= 1 << SEL2;
_delay_us(300);
PORTD &= ~(1 << SEL2);
_delay_us(300);
PORTD |= 1 << SEL2;
_delay_us(300);
mask = 1;
for(i=0;i<6;i++){
if(!(JOI2 & mask))
pulse_select1[i]=1;
else
pulse_select1[i]=0;
mask <<= 1;
}
PORTD &= ~(1 << SEL2);
_delay_us(300);
PORTD |= 1 << SEL2;
_delay_us(300);*/
////////////////////////////////////////////////////////////////////////////////////////
if(standart[D4]) {
keyboard_report.keycode[0] = KEY_V;
}
if(standart[D5]) {
keyboard_report.keycode[1] = KEY_C;
}
if(standart[D0]) {
keyboard_report.keycode[2] = UpArrow;
}
if(standart[D1]) {
keyboard_report.keycode[2] = DownArrow;
}
if(standart[D2]) {
keyboard_report.keycode[3] = LeftArrow;
}
if(standart[D3]) {
keyboard_report.keycode[3] = RightArrow;
}
if(low_select[D4]) {
keyboard_report.keycode[4] = KEY_N;
}
if(low_select[D5]) {
keyboard_report.keycode[5] = ENTER;
}
if(pulse_select[D0]) {
keyboard_report.keycode[0] = KEY_Z;
}
if(pulse_select[D1]) {
keyboard_report.keycode[1] = KEY_Y;
}
if(pulse_select[D2]) {
keyboard_report.keycode[4] = KEY_X;
}
if(pulse_select[D3]) {
keyboard_report.keycode[5] = KEY_1;
}
////////////////////////////////////////////////////////////////////////////////////////
/* if(standart1[D4]) {
keyboard_report_1.keycode[0] = KEY_E;
}
if(standart1[D5]) {
keyboard_report_1.keycode[1] = KEY_R;
}
if(standart1[D0]) {
keyboard_report_1.keycode[2] = KEY_W;
}
if(standart1[D1]) {
keyboard_report_1.keycode[2] = KEY_S;
}
if(standart1[D2]) {
keyboard_report_1.keycode[3] = KEY_A;
}
if(standart1[D3]) {
keyboard_report_1.keycode[3] = KEY_D;
}
if(low_select1[D4]) {
keyboard_report_1.keycode[4] = KEY_T;
}
if(low_select1[D5]) {
keyboard_report_1.keycode[5] = ENTER;
}*/
/*if(pulse_select1[D0]) {
keyboard_report_1.keycode[0] = KEY_F;
}
if(pulse_select1[D1]) {
keyboard_report_1.keycode[1] = KEY_G;
}
if(pulse_select1[D2]) {
keyboard_report_1.keycode[4] = KEY_H;
}
if(pulse_select1[D3]) {
keyboard_report_1.keycode[5] = KEY_2;
}*/
}
#define STATE_WAIT 0
#define STATE_SEND_KEY 1
#define STATE_RELEASE_KEY 2
int main() {
uchar i, button_release_counter = 0, state = STATE_WAIT, key, lastKey = 0, keyDidChange = 0;
uint8_t to_send = 1;
hardwareInit();
//DDRB = 1 << PB1; // PB0 as output
//PORTB = 1 << PB0; // PB1 is input with internal pullup resistor activated
for(i=0; i<sizeof(keyboard_report); i++) // clear report initially
((uchar *)&keyboard_report)[i] = 0;
for(i=0; i<sizeof(keyboard_report_1); i++) // clear report initially
((uchar *)&keyboard_report_1)[i] = 0;
wdt_enable(WDTO_1S); // enable 1s watchdog timer
usbInit();
usbDeviceDisconnect(); // enforce re-enumeration
for(i = 0; i<250; i++) { // wait 500 ms
wdt_reset(); // keep the watchdog happy
_delay_ms(2);
}
usbDeviceConnect();
//TCCR0B |= (1 << CS01); // timer 0 at clk/8 will generate randomness
sei(); // Enable interrupts after re-enumeration
//while(1) {
// wdt_reset(); // keep the watchdog happy
// usbPoll();
// key = keyPressed();
// if(lastKey != key){
// lastKey = key;
// keyDidChange = 1;
// }
/*if(!(PINB & (1<<PB1))) { // button pressed (PB1 at ground voltage)
// also check if some time has elapsed since last button press
if(state == STATE_WAIT && button_release_counter == 255)
state = STATE_SEND_KEY;
button_release_counter = 0; // now button needs to be released a while until retrigger
}
if(button_release_counter < 255)
button_release_counter++; // increase release counter
*/
// characters are sent when messageState == STATE_SEND and after receiving
// the initial LED state from PC (good way to wait until device is recognized)
//if(usbInterruptIsReady() && state != STATE_WAIT && LED_state != 0xff){
// if(usbInterruptIsReady()){
/*switch(state) {
case STATE_SEND_KEY:
buildReport('x');
state = STATE_RELEASE_KEY; // release next
break;
case STATE_RELEASE_KEY:
buildReport('0');
state = STATE_WAIT; // go back to waiting
break;
default:
state = STATE_WAIT; // should not happen
}*/
// buildReport(lastKey);
// start sending
// usbSetInterrupt((void *)&keyboard_report, sizeof(keyboard_report));
// }
//}
/* while (1)
{
usbPoll();
*/
/*
* this area is where you should set the movement
* and button values of the reports using the input
* method of your choice
*
*/
/*
if (memcmp(&keyboard_report, &keyboard_report_old, sizeof(keyboard_report_t)) != 0)
{
to_send = 1;
}
usbPoll();
if (to_send != 0)
{
// send the data if needed
usbSendHidReport(&keyboard_report, sizeof(keyboard_report_t));
}
usbPoll();
memcpy(&keyboard_report_old, &keyboard_report, sizeof(keyboard_report_t));
to_send = 0; // reset flag
}*/
while(1) {
wdt_reset(); // keep the watchdog happy
usbPoll();
keyPressed();
/*key = keyPressed();
if(lastKey != key){
lastKey = key;
keyDidChange = 1;
}*/
/*if(!(PINB & (1<<PB1))) { // button pressed (PB1 at ground voltage)
// also check if some time has elapsed since last button press
if(state == STATE_WAIT && button_release_counter == 255)
state = STATE_SEND_KEY;
button_release_counter = 0; // now button needs to be released a while until retrigger
}
if(button_release_counter < 255)
button_release_counter++; // increase release counter
*/
// characters are sent when messageState == STATE_SEND and after receiving
// the initial LED state from PC (good way to wait until device is recognized)
//if(usbInterruptIsReady() && state != STATE_WAIT && LED_state != 0xff){
/*if (memcmp(&keyboard_report, &keyboard_report_old, sizeof(keyboard_report)) != 0) {
to_send = 1;
}*/
if(usbInterruptIsReady()){
/*switch(state) {
case STATE_SEND_KEY:
buildReport('x');
state = STATE_RELEASE_KEY; // release next
break;
case STATE_RELEASE_KEY:
buildReport('0');
state = STATE_WAIT; // go back to waiting
break;
default:
state = STATE_WAIT; // should not happen
}*/
//buildReport(lastKey);
// start sending
usbSetInterrupt((void *)&keyboard_report, sizeof(keyboard_report));
}
/*if(usbInterruptIsReady()){
usbSetInterrupt((void *)&keyboard_report_1, sizeof(keyboard_report_1));
}*/
// memcpy(&keyboard_report_old, &keyboard_report, sizeof(keyboard_report));
//to_send = 0;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment