User interface library for databed on HEL medical exo.
Fork of UI by
UserInterface.cpp@6:e4bd0fd5befb, 2015-03-25 (annotated)
- Committer:
- nathanhonka
- Date:
- Wed Mar 25 03:27:37 2015 +0000
- Revision:
- 6:e4bd0fd5befb
- Parent:
- 1:7795fb7ee3f3
1) Add UI command type-checking.; 2) Create common.h, a common location for shared defintions between; Motion-Control and Data-Management projects (including recently defined; UI command type & members).
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mzling | 0:6b5a3a0138ad | 1 | #include "mbed.h" |
mzling | 0:6b5a3a0138ad | 2 | #include "MODSERIAL.h" |
mzling | 0:6b5a3a0138ad | 3 | #include "initDatabed.h" |
mzling | 0:6b5a3a0138ad | 4 | #include "UserInterface.h" |
nathanhonka | 6:e4bd0fd5befb | 5 | #include "common.h" |
mzling | 0:6b5a3a0138ad | 6 | |
mzling | 0:6b5a3a0138ad | 7 | // UI button variables |
mzling | 0:6b5a3a0138ad | 8 | //int buttonA = 1; // state of remote button |
mzling | 0:6b5a3a0138ad | 9 | //int buttonA_prev = 1; |
mzling | 0:6b5a3a0138ad | 10 | |
mzling | 0:6b5a3a0138ad | 11 | // push hold vars |
mzling | 0:6b5a3a0138ad | 12 | //float tHold = .6; // hold time for sit/stand |
mzling | 0:6b5a3a0138ad | 13 | //float tIdle = 2; // time out to confirm sit or stance (s) |
mzling | 0:6b5a3a0138ad | 14 | //int SSconfirm = 0; // sit/stand variable for confirmation process |
mzling | 0:6b5a3a0138ad | 15 | //float tRelease = .3; // time since last transmission to determine button release |
mzling | 0:6b5a3a0138ad | 16 | |
mzling | 0:6b5a3a0138ad | 17 | |
mzling | 0:6b5a3a0138ad | 18 | // various timers |
mzling | 0:6b5a3a0138ad | 19 | //Timer time_StateChange; |
mzling | 0:6b5a3a0138ad | 20 | //Timer time_pressA; |
mzling | 0:6b5a3a0138ad | 21 | //Timer time_pressB; |
mzling | 0:6b5a3a0138ad | 22 | |
mzling | 0:6b5a3a0138ad | 23 | //int buttonB = 1; // state of remote button |
mzling | 0:6b5a3a0138ad | 24 | //int buttonB_prev = 1; |
mzling | 0:6b5a3a0138ad | 25 | //char __xbeeBuffer[250]; |
mzling | 0:6b5a3a0138ad | 26 | //int _dataCnt=0; |
nathanhonka | 6:e4bd0fd5befb | 27 | UI_t UI = BUTTON_NONE; |
mzling | 0:6b5a3a0138ad | 28 | |
mzling | 0:6b5a3a0138ad | 29 | //float _time_sinceA, _time_sinceB; //time since the button was first pressed |
mzling | 0:6b5a3a0138ad | 30 | |
mzling | 0:6b5a3a0138ad | 31 | UserInterface::UserInterface(void): _buttonA(1), _buttonA_prev(1), _tHold(.6), _tIdle(2), _SSconfirm(0), _tRelease(.3), _buttonB(1), _buttonB_prev(1), _dataCnt(0) { |
mzling | 0:6b5a3a0138ad | 32 | } |
mzling | 0:6b5a3a0138ad | 33 | |
mzling | 0:6b5a3a0138ad | 34 | void UserInterface::readBuffer() |
mzling | 0:6b5a3a0138ad | 35 | { |
mzling | 0:6b5a3a0138ad | 36 | while (xbeeUI.readable() && _dataCnt<250) { |
mzling | 0:6b5a3a0138ad | 37 | _xbeeBuffer[_dataCnt] = xbeeUI.getc(); |
mzling | 0:6b5a3a0138ad | 38 | _dataCnt++; |
mzling | 0:6b5a3a0138ad | 39 | } |
mzling | 0:6b5a3a0138ad | 40 | } |
mzling | 0:6b5a3a0138ad | 41 | |
mzling | 0:6b5a3a0138ad | 42 | /** |
mzling | 0:6b5a3a0138ad | 43 | * This function returns an array of information about the received characters. count[0] is # of data bytes, count[1] is expected length of the message, given the data length bytes and presence |
mzling | 0:6b5a3a0138ad | 44 | * of escape characters. count[2] is position of the first data byte. |
mzling | 0:6b5a3a0138ad | 45 | * @param idx char array containing received data, beginning with the start byte 0x7e |
mzling | 0:6b5a3a0138ad | 46 | * @param count array that will contain the returned values |
mzling | 0:6b5a3a0138ad | 47 | * @author Michael Ling |
mzling | 0:6b5a3a0138ad | 48 | * @date 2/2/2015 |
mzling | 0:6b5a3a0138ad | 49 | */ |
mzling | 0:6b5a3a0138ad | 50 | void UserInterface::find_length(char *idx, int *count) |
mzling | 0:6b5a3a0138ad | 51 | { |
mzling | 0:6b5a3a0138ad | 52 | int pos = 0; |
mzling | 0:6b5a3a0138ad | 53 | short length; |
mzling | 0:6b5a3a0138ad | 54 | //This segment reads the length bytes (bytes 2-3 of the message) |
mzling | 0:6b5a3a0138ad | 55 | if (*(idx+1) == 0x7d) { |
mzling | 0:6b5a3a0138ad | 56 | length = (*(idx+2) ^ 0x20) << 8; |
mzling | 0:6b5a3a0138ad | 57 | pos = 3; |
mzling | 0:6b5a3a0138ad | 58 | } else { |
mzling | 0:6b5a3a0138ad | 59 | length = *(idx+1) << 8; |
mzling | 0:6b5a3a0138ad | 60 | pos = 2; |
mzling | 0:6b5a3a0138ad | 61 | } |
mzling | 0:6b5a3a0138ad | 62 | if (*(idx+pos) == 0x7d) { |
mzling | 0:6b5a3a0138ad | 63 | length = length | (*(idx+pos+1)^0x20); |
mzling | 0:6b5a3a0138ad | 64 | pos += 2; |
mzling | 0:6b5a3a0138ad | 65 | } else { |
mzling | 0:6b5a3a0138ad | 66 | length = length | *(idx+pos); |
mzling | 0:6b5a3a0138ad | 67 | pos += 1; |
mzling | 0:6b5a3a0138ad | 68 | } |
mzling | 0:6b5a3a0138ad | 69 | count[0] = (int)length; |
mzling | 0:6b5a3a0138ad | 70 | //Length incremented by 1--we treat the checksum as a data byte, since it can also be escaped |
mzling | 0:6b5a3a0138ad | 71 | length += 1; |
mzling | 0:6b5a3a0138ad | 72 | //Checks for escape characters--for every escape char found, the data section gets 1 byte longer |
mzling | 0:6b5a3a0138ad | 73 | for (short i = 0; i < length; i += 1) { |
mzling | 0:6b5a3a0138ad | 74 | if (*(idx+i) == 0x7d) { |
mzling | 0:6b5a3a0138ad | 75 | length += 1; |
mzling | 0:6b5a3a0138ad | 76 | } |
mzling | 0:6b5a3a0138ad | 77 | } |
mzling | 0:6b5a3a0138ad | 78 | count[1] = (int) length + 3; |
mzling | 0:6b5a3a0138ad | 79 | count[2] = pos; |
mzling | 0:6b5a3a0138ad | 80 | } |
mzling | 0:6b5a3a0138ad | 81 | |
mzling | 0:6b5a3a0138ad | 82 | /** |
mzling | 0:6b5a3a0138ad | 83 | * This function returns true if calculated checksum matches the checksum at the end of the message. |
mzling | 0:6b5a3a0138ad | 84 | * @param idx char array containing received data, starting with start byte 0x7e |
mzling | 0:6b5a3a0138ad | 85 | * @param length number of data bytes in the message |
mzling | 0:6b5a3a0138ad | 86 | * @author Michael Ling |
mzling | 0:6b5a3a0138ad | 87 | * @date 2/2/2015 |
mzling | 0:6b5a3a0138ad | 88 | */ |
mzling | 0:6b5a3a0138ad | 89 | bool UserInterface::checksum_check(char *idx, int length) |
mzling | 0:6b5a3a0138ad | 90 | { |
mzling | 0:6b5a3a0138ad | 91 | int pos = 0; |
mzling | 0:6b5a3a0138ad | 92 | int sum = 0; |
mzling | 0:6b5a3a0138ad | 93 | for(int i = 0; i < length; i++) { |
mzling | 0:6b5a3a0138ad | 94 | //In case of an escape character, the true value of the byte is the following byte XOR with 0x20 |
mzling | 0:6b5a3a0138ad | 95 | if (*(idx+pos) == 0x7d) { |
mzling | 0:6b5a3a0138ad | 96 | sum += (*(idx+pos+1) ^ 0x20); |
mzling | 0:6b5a3a0138ad | 97 | pos += 2; |
mzling | 0:6b5a3a0138ad | 98 | } else { |
mzling | 0:6b5a3a0138ad | 99 | sum += *(idx+pos); |
mzling | 0:6b5a3a0138ad | 100 | pos += 1; |
mzling | 0:6b5a3a0138ad | 101 | } |
mzling | 0:6b5a3a0138ad | 102 | } |
mzling | 0:6b5a3a0138ad | 103 | //XBEE checksum: sum all data bytes, truncate the sum to the rightmost 8 bytes, and subtract that from 0xff |
mzling | 0:6b5a3a0138ad | 104 | sum = sum & 0x0ff; |
mzling | 0:6b5a3a0138ad | 105 | char calcsum = (char)(0xff - sum); |
mzling | 0:6b5a3a0138ad | 106 | char checksum; |
mzling | 0:6b5a3a0138ad | 107 | if (*(idx+pos) == 0x7d) { |
mzling | 0:6b5a3a0138ad | 108 | checksum = *(idx+pos)^0x20; |
mzling | 0:6b5a3a0138ad | 109 | } else { |
mzling | 0:6b5a3a0138ad | 110 | checksum = *(idx+pos); |
mzling | 0:6b5a3a0138ad | 111 | } |
mzling | 0:6b5a3a0138ad | 112 | if (checksum != calcsum) { |
mzling | 0:6b5a3a0138ad | 113 | return false; |
mzling | 0:6b5a3a0138ad | 114 | } |
mzling | 0:6b5a3a0138ad | 115 | return true; |
mzling | 0:6b5a3a0138ad | 116 | } |
mzling | 0:6b5a3a0138ad | 117 | |
mzling | 0:6b5a3a0138ad | 118 | void UserInterface::checkUI_XBee() |
mzling | 0:6b5a3a0138ad | 119 | { |
mzling | 0:6b5a3a0138ad | 120 | int sum = 0; |
mzling | 0:6b5a3a0138ad | 121 | _buttonA_prev = _buttonA; |
mzling | 0:6b5a3a0138ad | 122 | _buttonB_prev = _buttonB; |
mzling | 0:6b5a3a0138ad | 123 | char * idx = strchr(_xbeeBuffer,0x7e); |
mzling | 0:6b5a3a0138ad | 124 | if (idx != NULL) { |
mzling | 0:6b5a3a0138ad | 125 | int size[3]; |
mzling | 0:6b5a3a0138ad | 126 | find_length(idx, size); |
mzling | 1:7795fb7ee3f3 | 127 | printf("Size: %d, Datacount: %d\r\n", size[1], _dataCnt); |
mzling | 0:6b5a3a0138ad | 128 | if(_dataCnt >= size[1]) { |
mzling | 0:6b5a3a0138ad | 129 | |
mzling | 0:6b5a3a0138ad | 130 | _buttonA = (_xbeeBuffer[idx-_xbeeBuffer+21]>>1) & 1; // on DIO1 |
mzling | 0:6b5a3a0138ad | 131 | _buttonB = (_xbeeBuffer[idx-_xbeeBuffer+21]>>2) & 1; // on DIO2 |
mzling | 0:6b5a3a0138ad | 132 | |
mzling | 0:6b5a3a0138ad | 133 | if (checksum_check(idx+size[2], size[0])) { |
mzling | 1:7795fb7ee3f3 | 134 | printf("Checksums match\r\n"); |
mzling | 0:6b5a3a0138ad | 135 | } else { |
mzling | 1:7795fb7ee3f3 | 136 | printf("Checksums don't match\r\n"); |
mzling | 0:6b5a3a0138ad | 137 | } |
mzling | 0:6b5a3a0138ad | 138 | _dataCnt = 0; |
mzling | 0:6b5a3a0138ad | 139 | } |
mzling | 0:6b5a3a0138ad | 140 | if(sum == 0x79c) { |
mzling | 0:6b5a3a0138ad | 141 | if (_buttonA == 0 && _buttonA_prev == 1) {//buton was just pressed |
mzling | 0:6b5a3a0138ad | 142 | _time_pressA.reset(); |
mzling | 0:6b5a3a0138ad | 143 | _time_pressA.start(); |
mzling | 0:6b5a3a0138ad | 144 | _time_sinceA = 0; |
mzling | 0:6b5a3a0138ad | 145 | } |
mzling | 0:6b5a3a0138ad | 146 | |
mzling | 0:6b5a3a0138ad | 147 | else if(_buttonA == 0) { |
mzling | 0:6b5a3a0138ad | 148 | _time_sinceA = _time_pressA; //button is still pressed |
mzling | 0:6b5a3a0138ad | 149 | } |
mzling | 0:6b5a3a0138ad | 150 | |
mzling | 0:6b5a3a0138ad | 151 | if (_buttonB == 0 && _buttonB_prev == 1) {//button was just pressed |
mzling | 0:6b5a3a0138ad | 152 | _time_pressB.reset(); |
mzling | 0:6b5a3a0138ad | 153 | _time_pressB.start(); |
mzling | 0:6b5a3a0138ad | 154 | _time_sinceB = 0; |
mzling | 0:6b5a3a0138ad | 155 | } else if(_buttonB == 0) { |
mzling | 0:6b5a3a0138ad | 156 | _time_sinceB = _time_pressB; //button is still pressed |
mzling | 0:6b5a3a0138ad | 157 | } |
mzling | 0:6b5a3a0138ad | 158 | } |
mzling | 0:6b5a3a0138ad | 159 | |
mzling | 0:6b5a3a0138ad | 160 | if((_time_pressA-_time_sinceA) >= _tRelease) { //button was released |
mzling | 0:6b5a3a0138ad | 161 | if(_time_pressA-_tRelease >= _tHold) { //if the button was held before released |
nathanhonka | 6:e4bd0fd5befb | 162 | UI = BUTTON_A_HOLD; //UI command is a held A button |
mzling | 0:6b5a3a0138ad | 163 | } else { |
nathanhonka | 6:e4bd0fd5befb | 164 | UI = BUTTON_A_PRESS; //UI command is a pressed A button |
mzling | 0:6b5a3a0138ad | 165 | } |
mzling | 0:6b5a3a0138ad | 166 | _buttonA = 1; //button A is released |
mzling | 0:6b5a3a0138ad | 167 | _time_pressA.stop(); //reset the button A timer |
mzling | 0:6b5a3a0138ad | 168 | _time_pressA.reset(); |
mzling | 0:6b5a3a0138ad | 169 | } |
mzling | 0:6b5a3a0138ad | 170 | if(_time_pressB-_time_sinceB >= _tRelease) { //button was released |
mzling | 0:6b5a3a0138ad | 171 | if(_time_pressB-_tRelease >= _tHold) { //if the button was held before released |
nathanhonka | 6:e4bd0fd5befb | 172 | UI = BUTTON_B_HOLD; //UI command is a held B button |
mzling | 0:6b5a3a0138ad | 173 | } else { |
nathanhonka | 6:e4bd0fd5befb | 174 | UI = BUTTON_B_PRESS; //UI command is a pressed B button |
mzling | 0:6b5a3a0138ad | 175 | } |
mzling | 0:6b5a3a0138ad | 176 | _buttonB = 1; //button B is released |
mzling | 0:6b5a3a0138ad | 177 | _time_pressB.stop(); //reset the button B timer |
mzling | 0:6b5a3a0138ad | 178 | _time_pressB.reset(); |
mzling | 0:6b5a3a0138ad | 179 | } |
mzling | 0:6b5a3a0138ad | 180 | } |
mzling | 0:6b5a3a0138ad | 181 | memset(_xbeeBuffer,0xFF,250); |
mzling | 0:6b5a3a0138ad | 182 | _dataCnt = 0; |
mzling | 0:6b5a3a0138ad | 183 | } |
mzling | 0:6b5a3a0138ad | 184 | |
mzling | 0:6b5a3a0138ad | 185 | /*void checkUI_XBee() |
mzling | 0:6b5a3a0138ad | 186 | { |
mzling | 0:6b5a3a0138ad | 187 | |
mzling | 0:6b5a3a0138ad | 188 | _buttonA_prev = _buttonA; |
mzling | 0:6b5a3a0138ad | 189 | buttonB_prev = buttonB; |
mzling | 0:6b5a3a0138ad | 190 | while (xbeeUI.readable() && _dataCnt<250) { |
mzling | 0:6b5a3a0138ad | 191 | __xbeeBuffer[_dataCnt] = xbeeUI.getc(); |
mzling | 0:6b5a3a0138ad | 192 | _dataCnt++; |
mzling | 0:6b5a3a0138ad | 193 | if (__xbeeBuffer[_dataCnt]==0x7e) { |
mzling | 0:6b5a3a0138ad | 194 | for(int i=0; i<22; i++) { |
mzling | 0:6b5a3a0138ad | 195 | if(xbeeUI.readable() { |
mzling | 0:6b5a3a0138ad | 196 | __xbeeBuffer[_dataCnt] = xbeeUI.getc(); |
mzling | 0:6b5a3a0138ad | 197 | _dataCnt++; |
mzling | 0:6b5a3a0138ad | 198 | } |
mzling | 0:6b5a3a0138ad | 199 | } |
mzling | 0:6b5a3a0138ad | 200 | } |
mzling | 0:6b5a3a0138ad | 201 | char * idx=strchr(__xbeeBuffer,0x7e); |
mzling | 0:6b5a3a0138ad | 202 | _buttonA = (_xbeeBuffer[idx-_xbeeBuffer+21]>>1) & 1; // on DIO1 |
mzling | 0:6b5a3a0138ad | 203 | buttonB = (_xbeeBuffer[idx-_xbeeBuffer+21]>>2) & 1; // on DIO2 |
mzling | 0:6b5a3a0138ad | 204 | pc.printf("%x\r\n", *(idx+2)); |
mzling | 0:6b5a3a0138ad | 205 | _dataCnt=0; |
mzling | 0:6b5a3a0138ad | 206 | if (buttonA == 0 && buttonA_prev==1) {//buton was just pressed |
mzling | 0:6b5a3a0138ad | 207 | time_pressA.reset(); |
mzling | 0:6b5a3a0138ad | 208 | time_pressA.start(); |
mzling | 0:6b5a3a0138ad | 209 | _time_sinceA=0; |
mzling | 0:6b5a3a0138ad | 210 | } |
mzling | 0:6b5a3a0138ad | 211 | |
mzling | 0:6b5a3a0138ad | 212 | else if(buttonA==0) { |
mzling | 0:6b5a3a0138ad | 213 | _time_sinceA=time_pressA; //button is still pressed |
mzling | 0:6b5a3a0138ad | 214 | } |
mzling | 0:6b5a3a0138ad | 215 | |
mzling | 0:6b5a3a0138ad | 216 | if (buttonB == 0 && buttonB_prev==1) {//button was just pressed |
mzling | 0:6b5a3a0138ad | 217 | time_pressB.reset(); |
mzling | 0:6b5a3a0138ad | 218 | time_pressB.start(); |
mzling | 0:6b5a3a0138ad | 219 | _time_sinceB=0; |
mzling | 0:6b5a3a0138ad | 220 | } else if(buttonB==0) { |
mzling | 0:6b5a3a0138ad | 221 | _time_sinceB=time_pressB; //button is still pressed |
mzling | 0:6b5a3a0138ad | 222 | } |
mzling | 0:6b5a3a0138ad | 223 | } |
mzling | 0:6b5a3a0138ad | 224 | if((time_pressA-_time_sinceA)>=tRelease) { //button was released |
mzling | 0:6b5a3a0138ad | 225 | if(time_pressA-tRelease>=tHold) { //if the button was held before released |
nathanhonka | 6:e4bd0fd5befb | 226 | UI=BUTTON_A_HOLD; //UI command is a held A button |
mzling | 0:6b5a3a0138ad | 227 | } else { |
nathanhonka | 6:e4bd0fd5befb | 228 | UI=BUTTON_A_PRESS; //UI command is a pressed A button |
mzling | 0:6b5a3a0138ad | 229 | } |
mzling | 0:6b5a3a0138ad | 230 | buttonA=1; //button A is released |
mzling | 0:6b5a3a0138ad | 231 | time_pressA.stop(); //reset the button A timer |
mzling | 0:6b5a3a0138ad | 232 | time_pressA.reset(); |
mzling | 0:6b5a3a0138ad | 233 | } |
mzling | 0:6b5a3a0138ad | 234 | if(time_pressB-_time_sinceB>=tRelease) { //button was released |
mzling | 0:6b5a3a0138ad | 235 | if(time_pressB-tRelease>=tHold) { //if the button was held before released |
nathanhonka | 6:e4bd0fd5befb | 236 | UI=BUTTON_B_HOLD; //UI command is a held B button |
mzling | 0:6b5a3a0138ad | 237 | } else { |
nathanhonka | 6:e4bd0fd5befb | 238 | UI=BUTTON_B_PRESS; //UI command is a pressed B button |
mzling | 0:6b5a3a0138ad | 239 | } |
mzling | 0:6b5a3a0138ad | 240 | buttonB=1; //button B is released |
mzling | 0:6b5a3a0138ad | 241 | time_pressB.stop(); //reset the button B timer |
mzling | 0:6b5a3a0138ad | 242 | time_pressB.reset(); |
mzling | 0:6b5a3a0138ad | 243 | } |
mzling | 0:6b5a3a0138ad | 244 | |
mzling | 0:6b5a3a0138ad | 245 | _dataCnt=0; |
mzling | 0:6b5a3a0138ad | 246 | memset(__xbeeBuffer,0xF,250); |
mzling | 0:6b5a3a0138ad | 247 | }*/ |
mzling | 0:6b5a3a0138ad | 248 | |
mzling | 0:6b5a3a0138ad | 249 | void UserInterface::initializeUI() |
mzling | 0:6b5a3a0138ad | 250 | { |
mzling | 0:6b5a3a0138ad | 251 | xbeeUI.baud(115200); |
mzling | 0:6b5a3a0138ad | 252 | mainPower = 0; |
mzling | 0:6b5a3a0138ad | 253 | |
mzling | 0:6b5a3a0138ad | 254 | } |