Changeset 4af90bf in avrstuff for V-USB_Dev/firmwares/CrO2/main.c
- Timestamp:
- Jan 14, 2012, 9:11:20 PM (12 years ago)
- Branches:
- main
- Children:
- e07597b
- Parents:
- 1fabcce
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
V-USB_Dev/firmwares/CrO2/main.c
r1fabcce r4af90bf 10 10 #include "usbdrv/usbdrv.h" 11 11 12 #define DDRIN DDRB 13 #define PORTIN PORTB 14 #define PININ PINB 12 static uint8_t ioblock[275]; // Max. Size of an MO5 standard block including sync header 13 static uint8_t status; // status bits 14 static uint16_t writePos; 15 static uint16_t blksz; 15 16 16 #define DDROUT DDRC 17 #define PORTOUT PORTC 17 static uint16_t readPos; 18 static uint8_t bitpos; 19 static uint8_t bit; // Currently generated bit 18 20 19 static uint8_t reportBuffer[5]; 20 static uint8_t buttons[6]; 21 static uint8_t idleRate; 21 int main() { 22 // Init 23 status = 0; 24 writePos = 0; 25 blksz = 0; 22 26 23 void main() {24 27 wdt_enable(WDTO_2S); 25 28 … … 27 30 usbInit(); 28 31 sei(); 29 bool doReport;30 32 31 DDROUT = 0; // Keyboard matrix out 32 PORTOUT = 255; // Enable pull up 33 // We put all pins as input then output a 0 in only one at a time. 34 // All the other pins are high-Z to avoid short circuits when many 35 // buttons are pressed. 36 DDRIN = 0; // Keyboard matrix in 37 PORTIN = 255; // Enable pull up 33 bit = 1; 34 bitpos = 0; 35 readPos = 0; 38 36 39 // configure timer 0 for a rate of 16M/(256 * 256) = ~244Hz 40 TCCR0 = 4; // timer 0 prescaler: 256 37 // Setup TIMER 1 for MFM pulses generation 38 TCCR1A = (1<<COM1A0); // Enable OC1A output 39 // CTC mode with OCR1A as MAXregister 40 TCCR1B = (1<<WGM12) | (1<<CS10); 41 OCR1A = 12800; // 800us bit clock 42 OCR1B = 6400; // Half-clock for 1 bits 43 TIMSK = (1 << OCIE1B) | (1 << OCIE1A); // interrupts on both timer matches. 41 44 42 reportBuffer[0] = 0; 43 doReport = false; 45 // TODO only start the timer when actually needed (start of block) 46 // and stop it when done. 47 DDRB |= 2; // OC1A/PB1 as output 48 44 49 45 50 while(1) { … … 47 52 usbPoll(); 48 53 49 for(int i = 0; i != 6; i++) { 50 DDROUT = 1<<i; 51 PORTOUT = ~(1<<i); 52 _delay_us(63); 53 if (buttons[i] != ((~PININ)&0x3F)) 54 { 55 doReport = true; 56 buttons[i] = (~PININ)&0x3F; 57 } 58 } 59 DDROUT = 0; 60 PORTOUT = 255; 61 62 // Copy lines 1 to 3 to the same lines in the report 63 for(int i=1; i != 4; i++) { 64 reportBuffer[i] = buttons[i]; 65 } 66 67 // Dispatch line 0 to report 1,2,3 (2 buttons each) 68 reportBuffer[1] |= (buttons[0] << 4)&0xC0; 69 reportBuffer[2] |= (buttons[0] << 2)&0xC0; 70 reportBuffer[3] |= (buttons[0])&0xC0; 71 72 // Copy part line 6 73 reportBuffer[4] = buttons[5]; // 2 btns left here 74 //reportBuffer[0] = buttons[4]; // this line is unused anyway, report as 75 // axis 76 77 if (doReport && usbInterruptIsReady()) { 78 usbSetInterrupt(reportBuffer, sizeof(reportBuffer)); 79 doReport = false; 80 } 54 // TODO send data to tape ! 81 55 } 82 56 } 83 57 84 58 85 static uint8_t protocolVer = 1; 86 uint8_t expectReport = 0;59 uint8_t usbFunctionSetup(uint8_t data[8]) { 60 usbRequest_t *rq = (void *)data; 87 61 88 89 char PROGMEM usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = { 90 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 91 0x09, 0x04, // USAGE (Joystick) 92 0xa1, 0x01, // COLLECTION (Application) 93 0xa1, 0x02, // COLLECTION (Logical) 94 95 0x75, 0x04, // REPORT_SIZE (8) 96 0x95, 0x02, // REPORT_COUNT (2) 97 0x15, 0x00, // LOGICAL_MINIMUM (0) 98 0x25, 0x0F, // LOGICAL_MAXIMUM (15) 99 0x35, 0x00, // PHYS_MINIMUM (0) 100 0x45, 0x0F, // PHYS_MAXIMUM (15) 101 0x09, 0x30, // USAGE (X) 102 0x09, 0x31, // USAGE (Y) 103 0x81, 0x02, // INPUT (Data,Var,Abs) 104 105 0x75, 0x01, // REPORT_SIZE (1) 106 0x95, 0x20, // REPORT_COUNT (32) 107 0x25, 0x01, // LOGICAL_MAXIMUM (1) 108 0x45, 0x01, // PHYSMAX (1) 109 0x05, 0x09, // USAGE_PAGE (Button) 110 0x19, 0x01, // USAGE_MINIMUM (Button 1) 111 0x29, 0x20, // USAGE_MAXIMUM (Button 32) 112 0x81, 0x02, // INPUT (Data,Var,Abs) 113 0xc0, // END_COLLECTION 114 0xc0 // END_COLLECTION 115 }; 116 117 118 uint8_t usbFunctionSetup(uint8_t data[8]) { 119 usbRequest_t *rq = (void *)data; 120 usbMsgPtr = reportBuffer; 121 if ((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) { 122 // class request type 123 if (rq->bRequest == USBRQ_HID_GET_REPORT) { 124 // wValue: ReportType (highbyte), ReportID (lowbyte) 125 // we only have one report type, so don't look at wValue 126 return sizeof(reportBuffer); 127 } else if (rq->bRequest == USBRQ_HID_SET_REPORT) { 128 if (rq->wLength.word == 1) { 129 // We expect one byte reports 130 expectReport = 1; 131 return 0xff; // Call usbFunctionWrite with data 132 } 133 } else if (rq->bRequest == USBRQ_HID_GET_IDLE) { 134 usbMsgPtr = &idleRate; 135 return 1; 136 } else if (rq->bRequest == USBRQ_HID_SET_IDLE) { 137 idleRate = rq->wValue.bytes[1]; 138 } else if (rq->bRequest == USBRQ_HID_GET_PROTOCOL) { 139 if (rq->wValue.bytes[1] < 1) { 140 protocolVer = rq->wValue.bytes[1]; 141 } 142 } else if(rq->bRequest == USBRQ_HID_SET_PROTOCOL) { 143 usbMsgPtr = &protocolVer; 144 return 1; 145 } 146 } else { 147 // no vendor specific requests implemented 148 } 149 return 0; 62 usbMsgPtr = ioblock; 63 switch(rq->bRequest) 64 { 65 case 0: 66 { /* CONFIGURE */ 67 status = rq->wValue.bytes[0]; 68 return 0; 69 } 70 case 1: 71 { /* RECEIVE/POLL DATA (TAPE > USB) */ 72 return 254; 73 } 74 case 2: 75 { 76 /* SEND DATA (USB > TAPE) */ 77 /* Get ready, actual data will come in usbFunctionWrite */ 78 // TODO store type of MO5 block + size in ioblock 79 writePos = 0; 80 blksz = rq->wLength.word; 81 return USB_NO_MSG; // Call usbFunctionWrite to send the data 82 } 83 } 84 return 0; 150 85 } 151 86 152 uint8_t usbFunctionWrite(uchar *data, uchar len) { 153 expectReport = 0; 154 return 0x01; 87 uint8_t usbFunctionWrite(uint8_t* data, uint8_t len) 88 { 89 // The data for a single request will be sent as slices of up to 8 bytes. 90 for (int i = 0; i < len; i++) 91 { 92 // TODO leave place for sync header and block type+size 93 ioblock[writePos++] = data[i]; 94 } 95 96 // TODO compute checksum as we go 97 98 return writePos>= blksz ? 1:0; 99 // returns 0: "needs more data" 100 // returns 1: "done" 101 // returns FF: "error" 155 102 } 156 103 104 ISR (TIMER1_COMPA_vect) 105 { 106 // generate next bit 107 bit = (ioblock[readPos] >> bitpos) & 1; 108 bitpos++; 109 if (bitpos > 7) 110 { 111 bitpos = 0; 112 readPos++; 113 if (readPos > 270) 114 readPos = 0; // TODO stop timer 115 } 116 } 117 118 ISR (TIMER1_COMPB_vect) 119 { 120 TCCR1A |= (bit << FOC1A); // Force toggle of A on B compare when generating a 1 bit 121 }
Note:
See TracChangeset
for help on using the changeset viewer.