📄 main.c
字号:
//redKontroll version 1.0 fredrikolofsson.com//GNU GPL v2 - See the OBDEV license for further details. (http://www.obdev.at/avrusb/)#include <avr/io.h>#include <avr/interrupt.h>#include <avr/pgmspace.h>#include <avr/wdt.h>#include <util/delay.h>#include "usbdrv.h"static void hardwareInit(void) { //--set pins to output DDRB= 0b00110000; //output pins for shiftin DDRD= 0b00000101; //output pins for usb //--internal pull-ups for inputs PORTD= 0b11111010; PORTB= 0b00001111; //--setup adc //ADCSRA |= (1<<ADPS0); //prescale 2 //ADCSRA |= (1<<ADPS1); //prescale 4 ADCSRA |= (1<<ADPS2); //prescale 16 //ADCSRA |= ((1<<ADPS2)|(1<<ADPS0)); //prescale 32 ADCSRA |= (1<<ADEN); //enable adc //--reset usb uchar i= 20; while(i) { //300ms _delay_ms(15); i--; } DDRD= 0;}static uchar reportBuffer[8]; /* buffer for HID reports */static uchar idleRate; /* in 4 ms units */uchar changed= 0;uchar shiftIn(void);uchar encoderIn(uchar currPin, uchar lastPin, uchar a, uchar b);PROGMEM char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = { //USB report descriptor 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x04, // USAGE (Joystick) 0xa1, 0x01, // COLLECTION (Application) 0x09, 0x30, // USAGE (shift) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) 0x75, 0x08, // REPORT_SIZE (8) 0x95, 0x01, // REPORT_COUNT (1) 0x81, 0x02, // INPUT (Data,Var,Abs) 0x09, 0x31, // USAGE (enc0) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) 0x75, 0x08, // REPORT_SIZE (8) 0x95, 0x01, // REPORT_COUNT (1) 0x81, 0x02, // INPUT (Data,Var,Abs) 0x09, 0x32, // USAGE (enc1) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) 0x75, 0x08, // REPORT_SIZE (8) 0x95, 0x01, // REPORT_COUNT (1) 0x81, 0x02, // INPUT (Data,Var,Abs) 0x09, 0x33, // USAGE (enc2) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) 0x75, 0x08, // REPORT_SIZE (8) 0x95, 0x01, // REPORT_COUNT (1) 0x81, 0x02, // INPUT (Data,Var,Abs) 0x09, 0x34, // USAGE (enc3) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) 0x75, 0x08, // REPORT_SIZE (8) 0x95, 0x01, // REPORT_COUNT (1) 0x81, 0x02, // INPUT (Data,Var,Abs) 0x09, 0x35, // USAGE (enc4) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) 0x75, 0x08, // REPORT_SIZE (8) 0x95, 0x01, // REPORT_COUNT (1) 0x81, 0x02, // INPUT (Data,Var,Abs) 0x09, 0x36, // USAGE (pot0) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) 0x75, 0x08, // REPORT_SIZE (8) 0x95, 0x01, // REPORT_COUNT (1) 0x81, 0x02, // INPUT (Data,Var,Abs) 0x09, 0x37, // USAGE (pot1) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) 0x75, 0x08, // REPORT_SIZE (8) 0x95, 0x01, // REPORT_COUNT (1) 0x81, 0x02, // INPUT (Data,Var,Abs) 0xc0 // END_COLLECTION};static void buildReport(uchar shift, uchar enc0, uchar enc1, uchar enc2, uchar enc3, uchar enc4, uchar pot0, uchar pot1) { reportBuffer[0]= shift; reportBuffer[1]= enc0; reportBuffer[2]= enc1; reportBuffer[3]= enc2; reportBuffer[4]= enc3; reportBuffer[5]= enc4; reportBuffer[6]= pot0; reportBuffer[7]= pot1;}uchar usbFunctionSetup(uchar data[8]) { usbRequest_t *rq = (void *)data; usbMsgPtr = reportBuffer; if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ /* class request type */ if(rq->bRequest == USBRQ_HID_GET_REPORT){ /* wValue: ReportType (highbyte), ReportID (lowbyte) */ /* we only have one report type, so don't look at wValue */ buildReport(0, 0, 0, 0, 0, 0, 0, 0); return sizeof(reportBuffer); }else if(rq->bRequest == USBRQ_HID_GET_IDLE){ usbMsgPtr = &idleRate; return 1; }else if(rq->bRequest == USBRQ_HID_SET_IDLE){ idleRate = rq->wValue.bytes[1]; } }else{ /* no vendor specific requests implemented */ } return 0;}int main(void) { uchar shift= 0, lastShift= 0; uchar lastPINB= PINB&0b00001111; uchar lastPIND= PIND&0b11111010; uchar enc0= 0, enc1= 0, enc2= 0, enc3= 0, enc4= 0, encTemp; uchar pot0= 0, pot1= 0; wdt_enable(WDTO_2S); hardwareInit(); usbInit(); sei(); //--main loop while(1) { wdt_reset(); usbPoll(); //--read digital inputs shift= shiftIn(); if(shift!=lastShift) { changed= 1; lastShift= shift; } //--read encoders encTemp= encoderIn(PIND&0b11111010, lastPIND, 1, 3); if(encTemp==1) { enc0--; changed= 2; lastPIND= PIND&0b11111010; } else if(encTemp==2) { enc0++; changed= 2; lastPIND= PIND&0b11111010; } encTemp= encoderIn(PIND&0b11111010, lastPIND, 4, 5); if(encTemp==1) { enc1--; changed= 2; lastPIND= PIND&0b11111010; } else if(encTemp==2) { enc1++; changed= 2; lastPIND= PIND&0b11111010; } encTemp= encoderIn(PIND&0b11111010, lastPIND, 6, 7); if(encTemp==1) { enc2--; changed= 2; lastPIND= PIND&0b11111010; } else if(encTemp==2) { enc2++; changed= 2; lastPIND= PIND&0b11111010; } encTemp= encoderIn(PINB&0b00001111, lastPINB, 0, 1); if(encTemp==1) { enc3--; changed= 3; lastPINB= PINB&0b00001111; } else if(encTemp==2) { enc3++; changed= 3; lastPINB= PINB&0b00001111; } encTemp= encoderIn(PINB&0b00001111, lastPINB, 2, 3); if(encTemp==1) { enc4--; changed= 3; lastPINB= PINB&0b00001111; } else if(encTemp==2) { enc4++; changed= 3; lastPINB= PINB&0b00001111; } //--read softpots ADMUX= 0b11000010; //select adc channel 2 ADCSRA |= (1<<ADSC); //start conversion while((ADCSRA&64)==64); //wait for ADSC bit to go low pot0= ADCL>>2; //skip 2 lowest bits pot0 |= (ADCH<<6); if(reportBuffer[6]!=pot0) { changed= 4; } ADMUX= 0b11000001; //select adc channel 1 ADCSRA |= (1<<ADSC); //start conversion while((ADCSRA&64)==64); //wait for ADSC bit to go low pot1= ADCL>>2; //skip 2 lowest bits pot1 |= (ADCH<<6); if(reportBuffer[7]!=pot1) { changed= 4; } //--send report if(usbInterruptIsReady()&&(changed>0)) { buildReport(shift, enc0, enc1, enc2, enc3, enc4, pot0, pot1); usbSetInterrupt(reportBuffer, sizeof(reportBuffer)); changed= 0; } } return 0;}uchar encoderIn(uchar currPin, uchar lastPin, uchar a, uchar b) { if((lastPin&(1<<a))!=(1<<a) && ((currPin&(1<<a))==(1<<a))) { if((currPin&(1<<b))!=(1<<b)) { return 2; } return 1; } else if((lastPin&(1<<a))==(1<<a) && ((currPin&(1<<a))!=(1<<a))) { if((currPin&(1<<b))==(1<<b)) { return 2; } return 1; } return 0;}uchar shiftIn(void) { char i; uchar data= 0; PORTB |= (1<<5); //set latch pin to collect parallel data _delay_us(20); PORTB &= ~(1<<5); //clear latch pin to transmit for(i= 7; i>=0; i--) { PORTB &= ~(1<<4); //clear clock pin if((PINC&(1<<0)) == (1<<0)) { data |= (1<<i); } PORTB |= (1<<4); //set clock pin } return data;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -