The iPod controller that I submitted for the mbed challenge

Dependencies:   mbed Motordriver PID

Committer:
networker
Date:
Wed May 04 15:41:13 2011 +0000
Revision:
0:371773dd3dd1
first publication

Who changed what in which revision?

UserRevisionLine numberNew contents of line
networker 0:371773dd3dd1 1 #include "mbed.h"
networker 0:371773dd3dd1 2 #include "keybrd.h"
networker 0:371773dd3dd1 3 #include <limits.h>
networker 0:371773dd3dd1 4
networker 0:371773dd3dd1 5 #define KEYS (0xFC)
networker 0:371773dd3dd1 6 #define PUSH (1<<1)
networker 0:371773dd3dd1 7 #define ROTA (1<<3)
networker 0:371773dd3dd1 8 #define ROTB (1<<4)
networker 0:371773dd3dd1 9 #define INPUTS (PUSH|ROTA|ROTB)
networker 0:371773dd3dd1 10
networker 0:371773dd3dd1 11 keybrd::keybrd(MCP23017& intf, PinName p): _eventhandler(0), _intf(intf), _keys(0), _lastkey(0), _pos(0), _oldpos(0), _state(0) {
networker 0:371773dd3dd1 12 printf("creating keyboard\n");
networker 0:371773dd3dd1 13 _min = INT_MIN;
networker 0:371773dd3dd1 14 _max = INT_MAX;
networker 0:371773dd3dd1 15 //inirq = new DigitalOut(LED3);
networker 0:371773dd3dd1 16 //*inirq = 0;
networker 0:371773dd3dd1 17 intr = new InterruptIn(p);
networker 0:371773dd3dd1 18 intr->mode(PullUp);
networker 0:371773dd3dd1 19 intr->fall(this, &keybrd::handler);
networker 0:371773dd3dd1 20 intf.interruptControl(PORT_A, 0); //interrupt on pin change from previous value
networker 0:371773dd3dd1 21 intf.interruptControl(PORT_B, 0); //interrupt on pin change from previous value
networker 0:371773dd3dd1 22 intf.interruptEnable(PORT_A, KEYS);//interrupt on key-press
networker 0:371773dd3dd1 23 intf.interruptEnable(PORT_B, INPUTS);//interrupt on change of rotary encoder
networker 0:371773dd3dd1 24 //printf("keyboard created\n");
networker 0:371773dd3dd1 25 }
networker 0:371773dd3dd1 26
networker 0:371773dd3dd1 27 unsigned short keybrd::get() {
networker 0:371773dd3dd1 28 _intf.readW(INTCAPA);
networker 0:371773dd3dd1 29 raw = ~_intf.readW(GPIOA);
networker 0:371773dd3dd1 30 raw &= (INPUTS<<8) | KEYS;
networker 0:371773dd3dd1 31 return raw;
networker 0:371773dd3dd1 32 }
networker 0:371773dd3dd1 33
networker 0:371773dd3dd1 34 void keybrd::handler() {
networker 0:371773dd3dd1 35 //there can be a PORT_A interrupt, meaning a change in the state of one of the 6 buttons
networker 0:371773dd3dd1 36 //or a PORT_B interrupt, meaning a change in the rotary encoder/button
networker 0:371773dd3dd1 37 //PORT_A, interrupt on pin_change, 3 registers: change, snapshot, actual
networker 0:371773dd3dd1 38 //read actual on both ports and compare to previous
networker 0:371773dd3dd1 39
networker 0:371773dd3dd1 40 //*inirq = 1;
networker 0:371773dd3dd1 41 if (_intf.isbusy()) {//the i2c interrupt is busy, so we postpone the read until it has finished
networker 0:371773dd3dd1 42 _intf.post(this, &keybrd::handler);
networker 0:371773dd3dd1 43 //*inirq = 0;
networker 0:371773dd3dd1 44 return;
networker 0:371773dd3dd1 45 }
networker 0:371773dd3dd1 46 unsigned short present = get();//read the relevant pins
networker 0:371773dd3dd1 47 char keys = (((present>>8) & PUSH) | present);
networker 0:371773dd3dd1 48 char released = _keys & ~keys;//bitmap of keys just released
networker 0:371773dd3dd1 49 char pressed = keys & ~_keys;//bitmap of keys just pressed
networker 0:371773dd3dd1 50 if (keys==0)
networker 0:371773dd3dd1 51 _lastkey = 0;
networker 0:371773dd3dd1 52 for (int i = 1; i < 8; i++) {
networker 0:371773dd3dd1 53 if (released & (1<<i))
networker 0:371773dd3dd1 54 handleEvent(keyup, i);
networker 0:371773dd3dd1 55 if (pressed & (1<<i)) {
networker 0:371773dd3dd1 56 _lastkey = i;
networker 0:371773dd3dd1 57 handleEvent(keydown, i);
networker 0:371773dd3dd1 58 }
networker 0:371773dd3dd1 59 }
networker 0:371773dd3dd1 60 //printf("!%04X %02X %02X %d\n", present, pressed, released, _lastkey);
networker 0:371773dd3dd1 61 _keys = keys;
networker 0:371773dd3dd1 62
networker 0:371773dd3dd1 63 present >>= 8;
networker 0:371773dd3dd1 64 present &= ROTA|ROTB;
networker 0:371773dd3dd1 65 switch (_state) {
networker 0:371773dd3dd1 66 case 0:
networker 0:371773dd3dd1 67 if (present & ROTA) _pos--;
networker 0:371773dd3dd1 68 else if (present & ROTB) _pos++;
networker 0:371773dd3dd1 69 break;
networker 0:371773dd3dd1 70 case ROTA:
networker 0:371773dd3dd1 71 if (present & ROTB) _pos--;
networker 0:371773dd3dd1 72 else if (!(present & ROTA)) _pos++;
networker 0:371773dd3dd1 73 break;
networker 0:371773dd3dd1 74 case ROTB:
networker 0:371773dd3dd1 75 if (!(present & ROTB)) _pos--;
networker 0:371773dd3dd1 76 else if (present & ROTA) _pos++;
networker 0:371773dd3dd1 77 break;
networker 0:371773dd3dd1 78 default://ROTA|ROTB
networker 0:371773dd3dd1 79 if (!(present & ROTA)) _pos--;
networker 0:371773dd3dd1 80 else if (!(present & ROTB)) _pos++;
networker 0:371773dd3dd1 81 break;
networker 0:371773dd3dd1 82 }
networker 0:371773dd3dd1 83 if (_pos>_max) _pos = wrap ? _min : _max;
networker 0:371773dd3dd1 84 else if (_pos<_min) _pos = wrap ? _max : _min;
networker 0:371773dd3dd1 85 _state = present & (ROTA|ROTB);
networker 0:371773dd3dd1 86
networker 0:371773dd3dd1 87 if (_state == 0)
networker 0:371773dd3dd1 88 if (_pos > _oldpos)
networker 0:371773dd3dd1 89 handleEvent(posup, _pos - _oldpos);
networker 0:371773dd3dd1 90 else if (_pos < _oldpos)
networker 0:371773dd3dd1 91 handleEvent(posdown, _oldpos - _pos);
networker 0:371773dd3dd1 92 _oldpos = _pos;
networker 0:371773dd3dd1 93 //*inirq = 0;
networker 0:371773dd3dd1 94 }