Changeset 08d5388 in avrstuff for aktoserial/code/main.c


Ignore:
Timestamp:
Jul 31, 2010, 9:35:39 AM (14 years ago)
Author:
Adrien Destugues <pulkomandy@…>
Branches:
main
Children:
38f2eef
Parents:
c6e02cf
Message:

Should-be_working version (but its not)

  • Amiga to usb keycodemap
  • Sending hid reports when a key is pressed

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • aktoserial/code/main.c

    rc6e02cf r08d5388  
    1 #define F_CPU 16000000UL
    2 
    31#include <avr/io.h>
     2#include <avr/interrupt.h>
     3#include <avr/wdt.h>
     4#include <avr/pgmspace.h>
     5#include <util/delay.h>
     6
     7#include <string.h>
    48
    59#include "amiga_keyboard/amiga_keyboard.h"
    6 #include "usart/usart.h"
     10#include "usbdrv/usbdrv.h"
     11#include "keycodes.h"
     12
     13const uint8_t PROGMEM keymatrix[128] = {
     14// 0         1                 2            3            4          5          6           7            8            9              A             B             C             D             E              F
     15KEY_grave,   KEY_1,            KEY_2,       KEY_3,       KEY_4,     KEY_5,     KEY_6,      KEY_7,       KEY_8,       KEY_9,         KEY_0,        KEY_minus,    KEY_equals,   KEY_backslash, KEY_Reserved,  KEY_KP0,      //0
     16KEY_Q,       KEY_W,            KEY_E,       KEY_R,       KEY_T,     KEY_Y,     KEY_U,      KEY_I,       KEY_O,       KEY_P,         KEY_rbracket, KEY_lbracket, KEY_Reserved, KEY_KP1,       KEY_KP2,       KEY_KP3,      //1
     17KEY_A,       KEY_S,            KEY_D,       KEY_F,       KEY_G,     KEY_H,     KEY_J,      KEY_K,       KEY_L,       KEY_semicolon, KEY_apostroph,KEY_hash,     KEY_Reserved, KEY_KP4,       KEY_KP5,       KEY_KP6,      //2
     18KEY_Euro,    KEY_Z,            KEY_X,       KEY_C,       KEY_V,     KEY_B,     KEY_N,      KEY_M,       KEY_comma,   KEY_dot,       KEY_slash,    KEY_Reserved, KEY_KPcomma,  KEY_KP7,       KEY_KP8,       KEY_KP9,      //3
     19KEY_Spacebar,KEY_DeleteForward,KEY_Tab,     KEY_KPenter, KEY_Return,KEY_ESCAPE,KEY_DELETE, KEY_Reserved,KEY_Reserved,KEY_Reserved,  KEY_KPminus,  KEY_Reserved, KEY_UpArrow,  KEY_DownArrow, KEY_RightArrow,KEY_LeftArrow,//4
     20KEY_F1,      KEY_F2,           KEY_F3,      KEY_F4,      KEY_F5,    KEY_F6,    KEY_F7,     KEY_F8,      KEY_F9,      KEY_F10,       KEY_KPRParen, KEY_KPLParen, KEY_KPslash,  KEY_KPasterisk,KEY_KPplus,    KEY_Help,     //5
     21KEY_Reserved,KEY_Reserved,     KEY_capslock,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,  KEY_Reserved,  KEY_Reserved, //6
     22KEY_Reserved,KEY_Reserved,     KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,  KEY_Reserved,  KEY_Reserved, //7
     23};
     24
     25/**
     26 * The modmatrix-array contains positions of the modifier-keys in the matrix.
     27 * It is built in the same way as the keymatrix-array.
     28 * \sa keymatrix
     29 */
     30const uint8_t PROGMEM modmatrix[8] = { // contains positions of modifiers in the matrix
     31  // 0             1               2                 3         4         5         6                  7
     32MOD_SHIFT_LEFT,MOD_SHIFT_RIGHT,MOD_NONE,MOD_CONTROL_LEFT,MOD_ALT_LEFT,MOD_NONE, MOD_GUI_LEFT, MOD_GUI_RIGHT,
     33};
     34
     35static uint8_t idleRate;
     36static uint8_t reportBuffer[8];
     37
     38void fillReportBuffer(uint8_t key_code) {
     39        uint8_t key, modifier;
     40        uint8_t reportIndex = 2; // reportBuffer[0] contains modifiers
     41        memset(reportBuffer, 0, sizeof(reportBuffer)); // clear report buffer
     42        key = pgm_read_byte(&keymatrix[key_code]);
     43        if (key_code >= 0x60 && key_code < 0x68)
     44                modifier = pgm_read_byte(&modmatrix[key_code - 0x60]);
     45        else
     46                modifier = MOD_NONE;
     47        if (key != KEY_Reserved) {
     48                reportBuffer[reportIndex] = key; // set next available entry
     49                reportIndex++;
     50        }
     51        reportBuffer[0] |= modifier;
     52}
     53
     54
     55void usbSendReport(uint8_t mode, uint8_t key) {
     56    // buffer for HID reports. we use a private one, so nobody gets disturbed
     57    uint8_t repBuffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
     58    repBuffer[0] = mode;
     59    repBuffer[2] = key;
     60    while (!usbInterruptIsReady()); // wait
     61    usbSetInterrupt(repBuffer, sizeof(repBuffer)); // send
     62}
     63
    764
    865int main() {
    9   //debug LED - output
    10   DDRD |= (1<<PD6);
    11 
    12   USARTInit(51);
    13   ak_init_keyboard();
    14 
    15   uint8_t key_code = 0;
    16 
    17   // Ready!
    18   USARTWriteChar('R');
    19 
    20   while(1) {
    21         key_code = ak_read_scancode();
    22     //USARTWriteChar(ak_scancode_to_ascii(key_code));
    23         USARTWriteHex((key_code >> 1) |(key_code << 7));
    24         USARTWriteChar(' ');
    25   }
    26  
    27   return 0;
    28 }
    29 
     66        uint8_t idleCounter = 0;
     67    uint8_t updateNeeded = 0;
     68
     69        wdt_enable(WDTO_2S);
     70    // configure timer 0 for a rate of 12M/(1024 * 256) = 45.78Hz (~22ms)
     71    TCCR0 = 5;          // timer 0 prescaler: 1024
     72
     73        //debug LED - output
     74        DDRD |= (1<<PD6);
     75
     76        // Keyboard
     77        uint8_t key_code = 0;
     78
     79        // USB
     80        usbInit();
     81        ak_init_keyboard();
     82        sei();
     83
     84        while(1) {
     85                wdt_reset();
     86                usbPoll();
     87
     88                updateNeeded = char_waiting;
     89
     90                if (char_waiting) {
     91                        key_code = ak_read_scancode();
     92                }
     93
     94                // check timer if we need periodic reports
     95                if (TIFR & (1 << TOV0)) {
     96                        TIFR = (1 << TOV0); // reset flag
     97                        if (idleRate != 0) { // do we need periodic reports?
     98                                if(idleCounter > 4){ // yes, but not yet
     99                                        idleCounter -= 5; // 22ms in units of 4ms
     100                                } else { // yes, it is time now
     101                                        updateNeeded = 1;
     102                                        idleCounter = idleRate;
     103                                }
     104                        }
     105
     106                }
     107                // if an update is needed, send the report
     108                if (updateNeeded && usbInterruptIsReady()) {
     109                        updateNeeded = 0;
     110                        //fillReportBuffer(key_code);
     111                        fillReportBuffer(KEY_Y);
     112                        usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
     113                        PORTD ^= (1<<PD6);
     114                }
     115        }
     116
     117        return 0;
     118}
     119
     120static uint8_t protocolVer = 1;
     121uint8_t expectReport = 0;
     122
     123#define LED_NUM     0x01  ///< num LED on a boot-protocol keyboard
     124#define LED_CAPS    0x02  ///< caps LED on a boot-protocol keyboard
     125#define LED_SCROLL  0x04  ///< scroll LED on a boot-protocol keyboard
     126#define LED_COMPOSE 0x08  ///< compose LED on a boot-protocol keyboard
     127#define LED_KANA    0x10  ///< kana LED on a boot-protocol keyboard
     128uint8_t LEDstate = 0;     ///< current state of the LEDs
     129
     130
     131char PROGMEM usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = {
     132        0x05, 0x01,   // USAGE_PAGE (Generic Desktop)
     133        0x09, 0x06,   // USAGE (Keyboard)
     134        0xa1, 0x01,   // COLLECTION (Application)
     135        0x05, 0x07,   //   USAGE_PAGE (Keyboard)
     136        0x19, 0xe0,   //   USAGE_MINIMUM (Keyboard LeftControl)
     137        0x29, 0xe7,   //   USAGE_MAXIMUM (Keyboard Right GUI)
     138        0x15, 0x00,   //   LOGICAL_MINIMUM (0)
     139        0x25, 0x01,   //   LOGICAL_MAXIMUM (1)
     140        0x75, 0x01,   //   REPORT_SIZE (1)
     141        0x95, 0x08,   //   REPORT_COUNT (8)
     142        0x81, 0x02,   //   INPUT (Data,Var,Abs)
     143        0x95, 0x01,   //   REPORT_COUNT (1)
     144        0x75, 0x08,   //   REPORT_SIZE (8)
     145        0x81, 0x03,   //   INPUT (Cnst,Var,Abs)
     146        0x95, 0x05,   //   REPORT_COUNT (5)
     147        0x75, 0x01,   //   REPORT_SIZE (1)
     148        0x05, 0x08,   //   USAGE_PAGE (LEDs)
     149        0x19, 0x01,   //   USAGE_MINIMUM (Num Lock)
     150        0x29, 0x05,   //   USAGE_MAXIMUM (Kana)
     151        0x91, 0x02,   //   OUTPUT (Data,Var,Abs)
     152        0x95, 0x01,   //   REPORT_COUNT (1)
     153        0x75, 0x03,   //   REPORT_SIZE (3)
     154        0x91, 0x03,   //   OUTPUT (Cnst,Var,Abs)
     155        0x95, 0x06,   //   REPORT_COUNT (6)
     156        0x75, 0x08,   //   REPORT_SIZE (8)
     157        0x15, 0x00,   //   LOGICAL_MINIMUM (0)
     158        0x25, 0x65,   //   LOGICAL_MAXIMUM (101)
     159        0x05, 0x07,   //   USAGE_PAGE (Keyboard)
     160        0x19, 0x00,   //   USAGE_MINIMUM (Reserved (no event indicated))
     161        0x29, 0x65,   //   USAGE_MAXIMUM (Keyboard Application)
     162        0x81, 0x00,   //   INPUT (Data,Ary,Abs)
     163        0xc0          // END_COLLECTION
     164};
     165
     166
     167
     168
     169uint8_t usbFunctionSetup(uint8_t data[8]) {
     170    usbRequest_t *rq = (void *)data;
     171    usbMsgPtr = reportBuffer;
     172    if ((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) {
     173        // class request type
     174        if (rq->bRequest == USBRQ_HID_GET_REPORT) {
     175            // wValue: ReportType (highbyte), ReportID (lowbyte)
     176            // we only have one report type, so don't look at wValue
     177            return sizeof(reportBuffer);
     178        } else if (rq->bRequest == USBRQ_HID_SET_REPORT) {
     179            if (rq->wLength.word == 1) {
     180                // We expect one byte reports
     181                expectReport = 1;
     182                return 0xff; // Call usbFunctionWrite with data
     183            }
     184        } else if (rq->bRequest == USBRQ_HID_GET_IDLE) {
     185            usbMsgPtr = &idleRate;
     186            return 1;
     187        } else if (rq->bRequest == USBRQ_HID_SET_IDLE) {
     188            idleRate = rq->wValue.bytes[1];
     189        } else if (rq->bRequest == USBRQ_HID_GET_PROTOCOL) {
     190            if (rq->wValue.bytes[1] < 1) {
     191                protocolVer = rq->wValue.bytes[1];
     192            }
     193        } else if(rq->bRequest == USBRQ_HID_SET_PROTOCOL) {
     194            usbMsgPtr = &protocolVer;
     195            return 1;
     196        }
     197    } else {
     198        // no vendor specific requests implemented
     199    }
     200    return 0;
     201}
     202
     203/**
     204 * The write function is called when LEDs should be set. Normally, we get only
     205 * one byte that contains info about the LED states.
     206 * \param data pointer to received data
     207 * \param len number ob bytes received
     208 * \return 0x01
     209 */
     210uint8_t usbFunctionWrite(uchar *data, uchar len) {
     211    if (expectReport && (len == 1)) {
     212        LEDstate = data[0]; // Get the state of all 5 LEDs
     213                /* TODO
     214        if (LEDstate & LED_NUM) { // light up caps lock
     215            PORTLEDS &= ~(1 << LEDNUM);
     216        } else {
     217            PORTLEDS |= (1 << LEDNUM);
     218        }
     219        if (LEDstate & LED_CAPS) { // light up caps lock
     220            PORTLEDS &= ~(1 << LEDCAPS);
     221        } else {
     222            PORTLEDS |= (1 << LEDCAPS);
     223        }
     224        if (LEDstate & LED_SCROLL) { // light up caps lock
     225            PORTLEDS &= ~(1 << LEDSCROLL);
     226        } else {
     227            PORTLEDS |= (1 << LEDSCROLL);
     228        }
     229                */
     230    }
     231    expectReport = 0;
     232    return 0x01;
     233}
     234
Note: See TracChangeset for help on using the changeset viewer.