Changeset 4af90bf in avrstuff for V-USB_Dev/firmwares/CrO2/main.c


Ignore:
Timestamp:
Jan 14, 2012, 9:11:20 PM (12 years ago)
Author:
Adrien Destugues <pulkomandy@…>
Branches:
main
Children:
e07597b
Parents:
1fabcce
Message:

work in progress CrO2:

  • USB configuration for a control endpoint with data payload
  • Timer setup for generating MFM stream

git-svn-id: svn://pulkomandy.tk/avrstuff@51 c6672c3c-f6b6-47f9-9001-1fd6b12fecbe

File:
1 edited

Legend:

Unmodified
Added
Removed
  • V-USB_Dev/firmwares/CrO2/main.c

    r1fabcce r4af90bf  
    1010#include "usbdrv/usbdrv.h"
    1111
    12 #define DDRIN DDRB
    13 #define PORTIN PORTB
    14 #define PININ PINB
     12static uint8_t ioblock[275]; // Max. Size of an MO5 standard block including sync header
     13static uint8_t status; // status bits
     14static uint16_t writePos;
     15static uint16_t blksz;
    1516
    16 #define DDROUT DDRC
    17 #define PORTOUT PORTC
     17static uint16_t readPos;
     18static uint8_t bitpos;
     19static uint8_t bit; // Currently generated bit
    1820
    19 static uint8_t reportBuffer[5];
    20 static uint8_t buttons[6];
    21 static uint8_t idleRate;
     21int main() {
     22        // Init
     23        status = 0;
     24        writePos = 0;
     25        blksz = 0;
    2226
    23 void main() {
    2427        wdt_enable(WDTO_2S);
    2528
     
    2730        usbInit();
    2831        sei();
    29         bool doReport;
    3032
    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;
    3836
    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.
    4144
    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
    4449
    4550        while(1) {
     
    4752                usbPoll();
    4853
    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 !
    8155        }
    8256}
    8357
    8458
    85 static uint8_t protocolVer = 1;
    86 uint8_t expectReport = 0;
     59uint8_t usbFunctionSetup(uint8_t data[8]) {
     60        usbRequest_t *rq = (void *)data;
    8761
    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;
    15085}
    15186
    152 uint8_t usbFunctionWrite(uchar *data, uchar len) {
    153     expectReport = 0;
    154     return 0x01;
     87uint8_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"
    155102}
    156103
     104ISR (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
     118ISR (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.