Published
Dependencies: BLE_API TLC5955 mbed nRF51822
Fork of BLE_LoopbackUART by
main.cpp@14:73923b07ae4a, 2018-06-09 (annotated)
- Committer:
- roysandberg
- Date:
- Sat Jun 09 23:23:06 2018 +0000
- Revision:
- 14:73923b07ae4a
- Parent:
- 13:15764cc1f12c
Published
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
yihui | 0:e910d9bb040f | 1 | /* mbed Microcontroller Library |
yihui | 0:e910d9bb040f | 2 | * Copyright (c) 2006-2013 ARM Limited |
yihui | 0:e910d9bb040f | 3 | * |
yihui | 0:e910d9bb040f | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
yihui | 0:e910d9bb040f | 5 | * you may not use this file except in compliance with the License. |
yihui | 0:e910d9bb040f | 6 | * You may obtain a copy of the License at |
yihui | 0:e910d9bb040f | 7 | * |
yihui | 0:e910d9bb040f | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
yihui | 0:e910d9bb040f | 9 | * |
yihui | 0:e910d9bb040f | 10 | * Unless required by applicable law or agreed to in writing, software |
yihui | 0:e910d9bb040f | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
yihui | 0:e910d9bb040f | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
yihui | 0:e910d9bb040f | 13 | * See the License for the specific language governing permissions and |
yihui | 0:e910d9bb040f | 14 | * limitations under the License. |
yihui | 0:e910d9bb040f | 15 | */ |
yihui | 0:e910d9bb040f | 16 | |
yihui | 0:e910d9bb040f | 17 | #include "mbed.h" |
rgrover1 | 12:33153cf38631 | 18 | #include "ble/BLE.h" |
roysandberg | 14:73923b07ae4a | 19 | #include "nrf_soc.h" // for internal temp sensor |
rgrover1 | 12:33153cf38631 | 20 | #include "ble/services/UARTService.h" |
roysandberg | 14:73923b07ae4a | 21 | #include "TLC5955.h" |
roysandberg | 14:73923b07ae4a | 22 | #include "sequencer.h" |
yihui | 0:e910d9bb040f | 23 | |
roysandberg | 14:73923b07ae4a | 24 | #include <ctype.h> |
roysandberg | 14:73923b07ae4a | 25 | |
roysandberg | 14:73923b07ae4a | 26 | #define INPUT_BUFFER_SIZE 256 |
roysandberg | 14:73923b07ae4a | 27 | |
roysandberg | 14:73923b07ae4a | 28 | |
roysandberg | 14:73923b07ae4a | 29 | #define NEED_CONSOLE_OUTPUT 1 /* Set this if you need debug messages on the console; |
Rohit Grover |
2:e060367b9024 | 30 | * it will have an impact on code-size and power consumption. */ |
yihui | 0:e910d9bb040f | 31 | |
Rohit Grover |
2:e060367b9024 | 32 | #if NEED_CONSOLE_OUTPUT |
rgrover1 | 6:e0fc9072e853 | 33 | #define DEBUG(...) { printf(__VA_ARGS__); } |
yihui | 0:e910d9bb040f | 34 | #else |
Rohit Grover |
2:e060367b9024 | 35 | #define DEBUG(...) /* nothing */ |
Rohit Grover |
2:e060367b9024 | 36 | #endif /* #if NEED_CONSOLE_OUTPUT */ |
yihui | 0:e910d9bb040f | 37 | |
roysandberg | 14:73923b07ae4a | 38 | extern void Sequencer(); |
roysandberg | 14:73923b07ae4a | 39 | extern void SequencerConfig(); |
roysandberg | 14:73923b07ae4a | 40 | extern void setChannelToRGB(int channel, uint16_t r, uint16_t g, uint16_t b); |
roysandberg | 14:73923b07ae4a | 41 | extern int getMode(); |
roysandberg | 14:73923b07ae4a | 42 | extern void setMode(int mode); |
roysandberg | 14:73923b07ae4a | 43 | extern uint32_t TheElapsedTime; |
roysandberg | 14:73923b07ae4a | 44 | |
roysandberg | 14:73923b07ae4a | 45 | extern uint16_t debugRedOut[(CHANNELS_PER_IC*NUMBER_OF_ICS)]; |
roysandberg | 14:73923b07ae4a | 46 | extern uint16_t debugGreenOut[(CHANNELS_PER_IC*NUMBER_OF_ICS)]; |
roysandberg | 14:73923b07ae4a | 47 | extern uint16_t debugBlueOut[(CHANNELS_PER_IC*NUMBER_OF_ICS)]; |
roysandberg | 14:73923b07ae4a | 48 | |
roysandberg | 14:73923b07ae4a | 49 | InterruptIn button1(P0_17); // button 1 on nRF51-DK. |
roysandberg | 14:73923b07ae4a | 50 | InterruptIn button2(P0_18); // button 2 |
roysandberg | 14:73923b07ae4a | 51 | InterruptIn button3(P0_19); // button 3 |
roysandberg | 14:73923b07ae4a | 52 | InterruptIn button4(P0_20); // button 4 |
roysandberg | 14:73923b07ae4a | 53 | |
roysandberg | 14:73923b07ae4a | 54 | uint8_t lastAmplitude = 100; |
yihui | 0:e910d9bb040f | 55 | |
roysandberg | 14:73923b07ae4a | 56 | uint8_t allRed=0; |
roysandberg | 14:73923b07ae4a | 57 | uint8_t allGreen=0; |
roysandberg | 14:73923b07ae4a | 58 | uint8_t allBlue=0; |
roysandberg | 14:73923b07ae4a | 59 | |
roysandberg | 14:73923b07ae4a | 60 | BLEDevice* ble; |
roysandberg | 14:73923b07ae4a | 61 | TLC5955* theChip; |
rgrover1 | 6:e0fc9072e853 | 62 | UARTService *uartServicePtr; |
yihui | 0:e910d9bb040f | 63 | |
roysandberg | 14:73923b07ae4a | 64 | // for use by string tokenizer. 10 tokens max |
roysandberg | 14:73923b07ae4a | 65 | char* tokenList[10]; |
roysandberg | 14:73923b07ae4a | 66 | |
roysandberg | 14:73923b07ae4a | 67 | char inputBuffer[INPUT_BUFFER_SIZE]; |
roysandberg | 14:73923b07ae4a | 68 | int inputBufferOffset = 0; |
roysandberg | 14:73923b07ae4a | 69 | int lastProcessedOffset = 0; |
roysandberg | 14:73923b07ae4a | 70 | int currentProcessedOffset = -1; |
roysandberg | 14:73923b07ae4a | 71 | int dataToProcess = FALSE; |
roysandberg | 14:73923b07ae4a | 72 | |
roysandberg | 14:73923b07ae4a | 73 | extern uint16_t UserAdjustableMovementInterval; |
roysandberg | 14:73923b07ae4a | 74 | |
rgrover1 | 13:15764cc1f12c | 75 | void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) |
yihui | 0:e910d9bb040f | 76 | { |
roysandberg | 14:73923b07ae4a | 77 | DEBUG("BLE Disconnected.\n\r"); |
roysandberg | 14:73923b07ae4a | 78 | ble->startAdvertising(); |
roysandberg | 14:73923b07ae4a | 79 | } |
roysandberg | 14:73923b07ae4a | 80 | |
roysandberg | 14:73923b07ae4a | 81 | void connectCallback(const Gap::ConnectionCallbackParams_t *params) |
roysandberg | 14:73923b07ae4a | 82 | { |
roysandberg | 14:73923b07ae4a | 83 | DEBUG("BLE Connected.\n\r"); |
roysandberg | 14:73923b07ae4a | 84 | ble->stopAdvertising(); |
Rohit Grover |
2:e060367b9024 | 85 | } |
yihui | 0:e910d9bb040f | 86 | |
rgrover1 | 12:33153cf38631 | 87 | void onDataWritten(const GattWriteCallbackParams *params) |
yihui | 0:e910d9bb040f | 88 | { |
rgrover1 | 12:33153cf38631 | 89 | if ((uartServicePtr != NULL) && (params->handle == uartServicePtr->getTXCharacteristicHandle())) { |
rgrover1 | 5:4bc41267a03a | 90 | uint16_t bytesRead = params->len; |
roysandberg | 14:73923b07ae4a | 91 | DEBUG("received %u bytes\n\r", bytesRead); |
roysandberg | 14:73923b07ae4a | 92 | for (int i=0; i< bytesRead;i++) { |
roysandberg | 14:73923b07ae4a | 93 | inputBuffer[inputBufferOffset] = params->data[i]; |
roysandberg | 14:73923b07ae4a | 94 | if (inputBuffer[inputBufferOffset] == 13 || inputBuffer[inputBufferOffset] == 10) { |
roysandberg | 14:73923b07ae4a | 95 | dataToProcess = TRUE; |
roysandberg | 14:73923b07ae4a | 96 | lastProcessedOffset = currentProcessedOffset; |
roysandberg | 14:73923b07ae4a | 97 | currentProcessedOffset = inputBufferOffset; |
roysandberg | 14:73923b07ae4a | 98 | } |
roysandberg | 14:73923b07ae4a | 99 | inputBufferOffset++; |
roysandberg | 14:73923b07ae4a | 100 | inputBufferOffset = inputBufferOffset % INPUT_BUFFER_SIZE; |
roysandberg | 14:73923b07ae4a | 101 | } |
yihui | 0:e910d9bb040f | 102 | } |
Rohit Grover |
2:e060367b9024 | 103 | } |
yihui | 0:e910d9bb040f | 104 | |
roysandberg | 14:73923b07ae4a | 105 | // limited to 20 chars |
roysandberg | 14:73923b07ae4a | 106 | void writeToBLE(const uint8_t* text) { |
roysandberg | 14:73923b07ae4a | 107 | ble->updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), text, strlen((char*)text)); |
roysandberg | 14:73923b07ae4a | 108 | } |
roysandberg | 14:73923b07ae4a | 109 | |
roysandberg | 14:73923b07ae4a | 110 | |
Rohit Grover |
2:e060367b9024 | 111 | void periodicCallback(void) |
Rohit Grover |
2:e060367b9024 | 112 | { |
roysandberg | 14:73923b07ae4a | 113 | Sequencer(); |
roysandberg | 14:73923b07ae4a | 114 | } |
roysandberg | 14:73923b07ae4a | 115 | |
roysandberg | 14:73923b07ae4a | 116 | int temperature_data_get(void) |
roysandberg | 14:73923b07ae4a | 117 | { |
roysandberg | 14:73923b07ae4a | 118 | int32_t temp; |
roysandberg | 14:73923b07ae4a | 119 | uint32_t err_code; |
roysandberg | 14:73923b07ae4a | 120 | |
roysandberg | 14:73923b07ae4a | 121 | err_code = sd_temp_get(&temp); |
roysandberg | 14:73923b07ae4a | 122 | |
roysandberg | 14:73923b07ae4a | 123 | // temp is recorded in 0.25C increments, accurate to +/-4 degrees |
roysandberg | 14:73923b07ae4a | 124 | return (int) (temp / 4); |
roysandberg | 14:73923b07ae4a | 125 | |
roysandberg | 14:73923b07ae4a | 126 | } |
roysandberg | 14:73923b07ae4a | 127 | |
roysandberg | 14:73923b07ae4a | 128 | typedef enum { |
roysandberg | 14:73923b07ae4a | 129 | STR2INT_SUCCESS, |
roysandberg | 14:73923b07ae4a | 130 | STR2INT_OVERFLOW, |
roysandberg | 14:73923b07ae4a | 131 | STR2INT_UNDERFLOW, |
roysandberg | 14:73923b07ae4a | 132 | STR2INT_INCONVERTIBLE |
roysandberg | 14:73923b07ae4a | 133 | } str2int_errno; |
roysandberg | 14:73923b07ae4a | 134 | |
roysandberg | 14:73923b07ae4a | 135 | /* |
roysandberg | 14:73923b07ae4a | 136 | Convert string s to int out. |
roysandberg | 14:73923b07ae4a | 137 | |
roysandberg | 14:73923b07ae4a | 138 | @param[out] out The converted int. Cannot be NULL. |
roysandberg | 14:73923b07ae4a | 139 | |
roysandberg | 14:73923b07ae4a | 140 | @param[in] s Input string to be converted. |
roysandberg | 14:73923b07ae4a | 141 | |
roysandberg | 14:73923b07ae4a | 142 | The format is the same as strtol, |
roysandberg | 14:73923b07ae4a | 143 | except that the following are inconvertible: |
roysandberg | 14:73923b07ae4a | 144 | |
roysandberg | 14:73923b07ae4a | 145 | - empty string |
roysandberg | 14:73923b07ae4a | 146 | - leading whitespace |
roysandberg | 14:73923b07ae4a | 147 | - any trailing characters that are not part of the number |
roysandberg | 14:73923b07ae4a | 148 | |
roysandberg | 14:73923b07ae4a | 149 | Cannot be NULL. |
roysandberg | 14:73923b07ae4a | 150 | |
roysandberg | 14:73923b07ae4a | 151 | @param[in] base Base to interpret string in. Same range as strtol (2 to 36). |
roysandberg | 14:73923b07ae4a | 152 | |
roysandberg | 14:73923b07ae4a | 153 | @return Indicates if the operation succeeded, or why it failed. |
roysandberg | 14:73923b07ae4a | 154 | */ |
roysandberg | 14:73923b07ae4a | 155 | str2int_errno str2int(long *out, char *s, int base) { |
roysandberg | 14:73923b07ae4a | 156 | char *end; |
roysandberg | 14:73923b07ae4a | 157 | //printf("str2int: s=%s\n\r",s); |
roysandberg | 14:73923b07ae4a | 158 | if (s[0] == '\0' || isspace((unsigned char) s[0])) |
roysandberg | 14:73923b07ae4a | 159 | return STR2INT_INCONVERTIBLE; |
roysandberg | 14:73923b07ae4a | 160 | //errno = 0; |
roysandberg | 14:73923b07ae4a | 161 | long l = strtol(s, &end, base); |
roysandberg | 14:73923b07ae4a | 162 | //printf("str2int: l=%ld\n\r", l); |
roysandberg | 14:73923b07ae4a | 163 | /* Both checks are needed because INT_MAX == LONG_MAX is possible. */ |
roysandberg | 14:73923b07ae4a | 164 | if (l > 65535 ) { |
roysandberg | 14:73923b07ae4a | 165 | printf("Overflow.\n\r"); |
roysandberg | 14:73923b07ae4a | 166 | return STR2INT_OVERFLOW; |
roysandberg | 14:73923b07ae4a | 167 | } |
roysandberg | 14:73923b07ae4a | 168 | if (l < 0 ) { |
roysandberg | 14:73923b07ae4a | 169 | printf("Underflow.\n\r"); |
roysandberg | 14:73923b07ae4a | 170 | return STR2INT_UNDERFLOW; |
roysandberg | 14:73923b07ae4a | 171 | } |
roysandberg | 14:73923b07ae4a | 172 | if (*end != '\0') { |
roysandberg | 14:73923b07ae4a | 173 | printf("Inconvertible.\n\r"); |
roysandberg | 14:73923b07ae4a | 174 | return STR2INT_INCONVERTIBLE; |
roysandberg | 14:73923b07ae4a | 175 | } |
roysandberg | 14:73923b07ae4a | 176 | printf("OK\n\r"); |
roysandberg | 14:73923b07ae4a | 177 | *out = l; |
roysandberg | 14:73923b07ae4a | 178 | return STR2INT_SUCCESS; |
roysandberg | 14:73923b07ae4a | 179 | } |
roysandberg | 14:73923b07ae4a | 180 | |
roysandberg | 14:73923b07ae4a | 181 | // duplicate string |
roysandberg | 14:73923b07ae4a | 182 | char* strdup ( char* s) { |
roysandberg | 14:73923b07ae4a | 183 | char *d = (char*) malloc (strlen (s) + 1); // Space for length plus nul |
roysandberg | 14:73923b07ae4a | 184 | if (d == NULL) return NULL; // No memory |
roysandberg | 14:73923b07ae4a | 185 | strcpy (d,s); // Copy the characters |
roysandberg | 14:73923b07ae4a | 186 | return d; // Return the new string |
roysandberg | 14:73923b07ae4a | 187 | } |
roysandberg | 14:73923b07ae4a | 188 | |
roysandberg | 14:73923b07ae4a | 189 | // http://stackoverflow.com/questions/9210528/split-string-with-delimiters-in-c |
roysandberg | 14:73923b07ae4a | 190 | char** str_split(char* a_str, char a_delim) |
roysandberg | 14:73923b07ae4a | 191 | { |
roysandberg | 14:73923b07ae4a | 192 | //char** result = 0; |
roysandberg | 14:73923b07ae4a | 193 | size_t count = 0; |
roysandberg | 14:73923b07ae4a | 194 | char* tmp = a_str; |
roysandberg | 14:73923b07ae4a | 195 | char* last_comma = 0; |
roysandberg | 14:73923b07ae4a | 196 | char delim[2]; |
roysandberg | 14:73923b07ae4a | 197 | delim[0] = a_delim; |
roysandberg | 14:73923b07ae4a | 198 | delim[1] = 0; |
roysandberg | 14:73923b07ae4a | 199 | |
roysandberg | 14:73923b07ae4a | 200 | /* Count how many elements will be extracted. */ |
roysandberg | 14:73923b07ae4a | 201 | while (*tmp) |
roysandberg | 14:73923b07ae4a | 202 | { |
roysandberg | 14:73923b07ae4a | 203 | if (a_delim == *tmp) |
roysandberg | 14:73923b07ae4a | 204 | { |
roysandberg | 14:73923b07ae4a | 205 | count++; |
roysandberg | 14:73923b07ae4a | 206 | last_comma = tmp; |
roysandberg | 14:73923b07ae4a | 207 | } |
roysandberg | 14:73923b07ae4a | 208 | tmp++; |
roysandberg | 14:73923b07ae4a | 209 | } |
roysandberg | 14:73923b07ae4a | 210 | |
roysandberg | 14:73923b07ae4a | 211 | /* Add space for trailing token. */ |
roysandberg | 14:73923b07ae4a | 212 | count += last_comma < (a_str + strlen(a_str) - 1); |
roysandberg | 14:73923b07ae4a | 213 | |
roysandberg | 14:73923b07ae4a | 214 | /* Add space for terminating null string so caller |
roysandberg | 14:73923b07ae4a | 215 | knows where the list of returned strings ends. */ |
roysandberg | 14:73923b07ae4a | 216 | count++; |
roysandberg | 14:73923b07ae4a | 217 | |
roysandberg | 14:73923b07ae4a | 218 | //result = malloc(sizeof(char*) * count); |
roysandberg | 14:73923b07ae4a | 219 | |
roysandberg | 14:73923b07ae4a | 220 | |
roysandberg | 14:73923b07ae4a | 221 | size_t idx = 0; |
roysandberg | 14:73923b07ae4a | 222 | char* token = strtok(a_str, delim); |
roysandberg | 14:73923b07ae4a | 223 | |
roysandberg | 14:73923b07ae4a | 224 | while (token) |
roysandberg | 14:73923b07ae4a | 225 | { |
roysandberg | 14:73923b07ae4a | 226 | //assert(idx < count); |
roysandberg | 14:73923b07ae4a | 227 | *(tokenList + idx++) = strdup(token); |
roysandberg | 14:73923b07ae4a | 228 | token = strtok(0, delim); |
roysandberg | 14:73923b07ae4a | 229 | } |
roysandberg | 14:73923b07ae4a | 230 | //assert(idx == count - 1); |
roysandberg | 14:73923b07ae4a | 231 | *(tokenList + idx) = 0; |
roysandberg | 14:73923b07ae4a | 232 | |
roysandberg | 14:73923b07ae4a | 233 | return tokenList; |
roysandberg | 14:73923b07ae4a | 234 | } |
roysandberg | 14:73923b07ae4a | 235 | |
roysandberg | 14:73923b07ae4a | 236 | int getTokenCount(char** tokens) { |
roysandberg | 14:73923b07ae4a | 237 | int i; |
roysandberg | 14:73923b07ae4a | 238 | for (i=0; tokens[i] != 0;i++); |
roysandberg | 14:73923b07ae4a | 239 | return i; |
roysandberg | 14:73923b07ae4a | 240 | } |
roysandberg | 14:73923b07ae4a | 241 | |
roysandberg | 14:73923b07ae4a | 242 | void RemoveSpaces(char* source) |
roysandberg | 14:73923b07ae4a | 243 | { |
roysandberg | 14:73923b07ae4a | 244 | char* i = source; |
roysandberg | 14:73923b07ae4a | 245 | char* j = source; |
roysandberg | 14:73923b07ae4a | 246 | while(*j != 0) |
roysandberg | 14:73923b07ae4a | 247 | { |
roysandberg | 14:73923b07ae4a | 248 | *i = *j++; |
roysandberg | 14:73923b07ae4a | 249 | if(*i != ' ') |
roysandberg | 14:73923b07ae4a | 250 | i++; |
roysandberg | 14:73923b07ae4a | 251 | } |
roysandberg | 14:73923b07ae4a | 252 | *i = 0; |
Rohit Grover |
2:e060367b9024 | 253 | } |
yihui | 0:e910d9bb040f | 254 | |
roysandberg | 14:73923b07ae4a | 255 | |
roysandberg | 14:73923b07ae4a | 256 | |
roysandberg | 14:73923b07ae4a | 257 | void parseInputData() { |
roysandberg | 14:73923b07ae4a | 258 | char inputLine[256]; |
roysandberg | 14:73923b07ae4a | 259 | char outputLine[256]; |
roysandberg | 14:73923b07ae4a | 260 | int j=0; |
roysandberg | 14:73923b07ae4a | 261 | long channel, r, g, b; |
roysandberg | 14:73923b07ae4a | 262 | |
roysandberg | 14:73923b07ae4a | 263 | for (int i=lastProcessedOffset+1; i != currentProcessedOffset; j++, i++) { |
roysandberg | 14:73923b07ae4a | 264 | i = i % INPUT_BUFFER_SIZE; |
roysandberg | 14:73923b07ae4a | 265 | inputLine[j] = tolower(inputBuffer[i]); |
roysandberg | 14:73923b07ae4a | 266 | } |
roysandberg | 14:73923b07ae4a | 267 | inputLine[j] = 0; |
roysandberg | 14:73923b07ae4a | 268 | |
roysandberg | 14:73923b07ae4a | 269 | RemoveSpaces(inputLine); |
roysandberg | 14:73923b07ae4a | 270 | |
roysandberg | 14:73923b07ae4a | 271 | // TODO: Define input command to set channel to color name or to R,G,B setting |
roysandberg | 14:73923b07ae4a | 272 | // Define way to set color correction factors for R,G,B |
roysandberg | 14:73923b07ae4a | 273 | // Test color correction |
roysandberg | 14:73923b07ae4a | 274 | char** tokens = str_split(inputLine, ','); |
roysandberg | 14:73923b07ae4a | 275 | int count = getTokenCount(tokens); |
roysandberg | 14:73923b07ae4a | 276 | printf("%d tokens:\n\r", count); |
roysandberg | 14:73923b07ae4a | 277 | for (int i=0; i< count; i++) { |
roysandberg | 14:73923b07ae4a | 278 | printf("%s\n\r",tokens[i]); |
roysandberg | 14:73923b07ae4a | 279 | } |
roysandberg | 14:73923b07ae4a | 280 | // inputLine is the input string without the trailing carriage return, all lower case |
roysandberg | 14:73923b07ae4a | 281 | if (!strcmp(tokens[0],"temp") || !strcmp(tokens[0],"temperature")) { |
roysandberg | 14:73923b07ae4a | 282 | // get the temperature |
roysandberg | 14:73923b07ae4a | 283 | sprintf(outputLine,"%dC",temperature_data_get()); |
roysandberg | 14:73923b07ae4a | 284 | writeToBLE((const uint8_t*)outputLine); |
roysandberg | 14:73923b07ae4a | 285 | } else if (!strcmp(tokens[0],"a") || !strcmp(tokens[0],"amp") || !strcmp(tokens[0],"amplitude")) { |
roysandberg | 14:73923b07ae4a | 286 | long val; |
roysandberg | 14:73923b07ae4a | 287 | if (str2int(&val, tokens[1], 10) == STR2INT_SUCCESS) { |
roysandberg | 14:73923b07ae4a | 288 | if (val < 5) val = 5; |
roysandberg | 14:73923b07ae4a | 289 | if (val > 100) val = 100; |
roysandberg | 14:73923b07ae4a | 290 | lastAmplitude = (uint8_t) val; |
roysandberg | 14:73923b07ae4a | 291 | rebuildGammaTables((uint8_t) ((val*0xFF)/100)); |
roysandberg | 14:73923b07ae4a | 292 | } |
roysandberg | 14:73923b07ae4a | 293 | |
roysandberg | 14:73923b07ae4a | 294 | } else if (!strcmp(tokens[0],"c") || !strcmp(tokens[0],"chan") || !strcmp(tokens[0],"channel")) { |
roysandberg | 14:73923b07ae4a | 295 | if (getTokenCount(tokens) == 5) { |
roysandberg | 14:73923b07ae4a | 296 | //printf("Processing chan.\n\r"); |
roysandberg | 14:73923b07ae4a | 297 | // tokens are command name, channel, r, g, b |
roysandberg | 14:73923b07ae4a | 298 | if (str2int(&channel, tokens[1], 10) == STR2INT_SUCCESS && |
roysandberg | 14:73923b07ae4a | 299 | str2int(&r, tokens[2], 16) == STR2INT_SUCCESS && |
roysandberg | 14:73923b07ae4a | 300 | str2int(&g, tokens[3], 16) == STR2INT_SUCCESS && |
roysandberg | 14:73923b07ae4a | 301 | str2int(&b, tokens[4], 16) == STR2INT_SUCCESS) { |
roysandberg | 14:73923b07ae4a | 302 | setMode(0); |
roysandberg | 14:73923b07ae4a | 303 | sprintf(outputLine, "%d: %x,%x,%x", (uint16_t) channel, (uint16_t) r, (uint16_t) g, (uint16_t) b); |
roysandberg | 14:73923b07ae4a | 304 | printf ("%s\n\r", outputLine); |
roysandberg | 14:73923b07ae4a | 305 | //wait(0.03) |
roysandberg | 14:73923b07ae4a | 306 | writeToBLE((const uint8_t*)outputLine); |
roysandberg | 14:73923b07ae4a | 307 | setChannelToRGB( (int) channel, (uint16_t) r, (uint16_t) g, (uint16_t) b); |
roysandberg | 14:73923b07ae4a | 308 | theChip->latchData(); |
roysandberg | 14:73923b07ae4a | 309 | } |
roysandberg | 14:73923b07ae4a | 310 | } |
roysandberg | 14:73923b07ae4a | 311 | } else if (!strcmp(tokens[0],"list")) { |
roysandberg | 14:73923b07ae4a | 312 | printf("Processing list.\n\r"); |
roysandberg | 14:73923b07ae4a | 313 | |
roysandberg | 14:73923b07ae4a | 314 | // output all channel settings |
roysandberg | 14:73923b07ae4a | 315 | for (int i=0; i< CHANNELS_PER_IC * NUMBER_OF_ICS; i++) { |
roysandberg | 14:73923b07ae4a | 316 | sprintf(outputLine, "%d: %x, %x, %x", i, debugRedOut[i], debugGreenOut[i], debugBlueOut[i]); |
roysandberg | 14:73923b07ae4a | 317 | writeToBLE((const uint8_t*)outputLine); |
roysandberg | 14:73923b07ae4a | 318 | wait(0.03); |
roysandberg | 14:73923b07ae4a | 319 | } |
roysandberg | 14:73923b07ae4a | 320 | } else if (!strcmp(tokens[0],"time")) { |
roysandberg | 14:73923b07ae4a | 321 | long theTime; |
roysandberg | 14:73923b07ae4a | 322 | if (str2int(&theTime, tokens[1], 10) == STR2INT_SUCCESS) { |
roysandberg | 14:73923b07ae4a | 323 | TheElapsedTime = ((theTime/100)-1)*60*60*1000 + ((theTime%100)*60*1000) - CLOCK_GRANULARITY; |
roysandberg | 14:73923b07ae4a | 324 | } |
roysandberg | 14:73923b07ae4a | 325 | } else if (!strcmp(tokens[0],"m") || !strcmp(tokens[0],"mode")) { |
roysandberg | 14:73923b07ae4a | 326 | long mode; |
roysandberg | 14:73923b07ae4a | 327 | if (str2int(&mode, tokens[1], 10) == STR2INT_SUCCESS) { |
roysandberg | 14:73923b07ae4a | 328 | setMode(mode); |
roysandberg | 14:73923b07ae4a | 329 | printf("Set mode to %d\n\r", getMode()); |
roysandberg | 14:73923b07ae4a | 330 | writeToBLE("Set mode."); |
roysandberg | 14:73923b07ae4a | 331 | } |
roysandberg | 14:73923b07ae4a | 332 | } else if (!strcmp(tokens[0],"interval") || !strcmp(tokens[0],"int")) { |
roysandberg | 14:73923b07ae4a | 333 | long movementInterval; |
roysandberg | 14:73923b07ae4a | 334 | if (str2int(&movementInterval, tokens[1], 10) == STR2INT_SUCCESS) { |
roysandberg | 14:73923b07ae4a | 335 | if (movementInterval < 300) movementInterval = 300; |
roysandberg | 14:73923b07ae4a | 336 | if (movementInterval > 10000) movementInterval = 10000; |
roysandberg | 14:73923b07ae4a | 337 | UserAdjustableMovementInterval = (uint16_t) movementInterval; |
roysandberg | 14:73923b07ae4a | 338 | } |
roysandberg | 14:73923b07ae4a | 339 | } else if (!strcmp(tokens[0],"base") || !strcmp(tokens[0],"b")) { |
roysandberg | 14:73923b07ae4a | 340 | printf ("Got base.\n\r"); |
roysandberg | 14:73923b07ae4a | 341 | if (getTokenCount(tokens) == 5) { |
roysandberg | 14:73923b07ae4a | 342 | int dither = ditherToEnum(tokens[1]); |
roysandberg | 14:73923b07ae4a | 343 | int effect = effectToEnum(tokens[2]); |
roysandberg | 14:73923b07ae4a | 344 | const int* colorList = colorListToPointer(tokens[3]); |
roysandberg | 14:73923b07ae4a | 345 | long timeConstant; |
roysandberg | 14:73923b07ae4a | 346 | // set a fixed base until mode is reset |
roysandberg | 14:73923b07ae4a | 347 | if (dither != -1 && |
roysandberg | 14:73923b07ae4a | 348 | effect != -1 && |
roysandberg | 14:73923b07ae4a | 349 | colorList != NULL && |
roysandberg | 14:73923b07ae4a | 350 | str2int(&timeConstant, tokens[4], 10) == STR2INT_SUCCESS) { |
roysandberg | 14:73923b07ae4a | 351 | |
roysandberg | 14:73923b07ae4a | 352 | if (getMode() == USER_MOVEMENT || getMode() == USER_MOVEMENT_AND_BASE) { |
roysandberg | 14:73923b07ae4a | 353 | setMode(USER_MOVEMENT_AND_BASE); |
roysandberg | 14:73923b07ae4a | 354 | } else { |
roysandberg | 14:73923b07ae4a | 355 | setMode(USER_BASE); |
roysandberg | 14:73923b07ae4a | 356 | } |
roysandberg | 14:73923b07ae4a | 357 | printf("Setting base.\n\r"); |
roysandberg | 14:73923b07ae4a | 358 | setBaseEffect( dither, effect, colorList, (int) timeConstant*100 ); |
roysandberg | 14:73923b07ae4a | 359 | writeToBLE("Base set."); |
roysandberg | 14:73923b07ae4a | 360 | } else { |
roysandberg | 14:73923b07ae4a | 361 | writeToBLE("Err: Parsing."); |
roysandberg | 14:73923b07ae4a | 362 | } |
roysandberg | 14:73923b07ae4a | 363 | } else { |
roysandberg | 14:73923b07ae4a | 364 | writeToBLE("Err: Token count."); |
roysandberg | 14:73923b07ae4a | 365 | } |
roysandberg | 14:73923b07ae4a | 366 | } else if (!strcmp(tokens[0],"effect") || !strcmp(tokens[0],"e")) { |
roysandberg | 14:73923b07ae4a | 367 | if (getTokenCount(tokens) == 8) { |
roysandberg | 14:73923b07ae4a | 368 | int movement = movementToEnum(tokens[1]); |
roysandberg | 14:73923b07ae4a | 369 | int dither = ditherToEnum(tokens[2]); |
roysandberg | 14:73923b07ae4a | 370 | int fill = fillToEnum(tokens[3]); |
roysandberg | 14:73923b07ae4a | 371 | int effect = effectToEnum(tokens[4]); |
roysandberg | 14:73923b07ae4a | 372 | const int* colorList = colorListToPointer(tokens[5]); |
roysandberg | 14:73923b07ae4a | 373 | long timeConstant; |
roysandberg | 14:73923b07ae4a | 374 | long moveTimeConstant; |
roysandberg | 14:73923b07ae4a | 375 | // set a fixed base until mode is reset |
roysandberg | 14:73923b07ae4a | 376 | if (movement != -1 && |
roysandberg | 14:73923b07ae4a | 377 | dither != -1 && |
roysandberg | 14:73923b07ae4a | 378 | effect != -1 && |
roysandberg | 14:73923b07ae4a | 379 | colorList != NULL & |
roysandberg | 14:73923b07ae4a | 380 | str2int(&timeConstant, tokens[6], 10) == STR2INT_SUCCESS && |
roysandberg | 14:73923b07ae4a | 381 | str2int(&moveTimeConstant, tokens[7], 10) == STR2INT_SUCCESS) { |
roysandberg | 14:73923b07ae4a | 382 | |
roysandberg | 14:73923b07ae4a | 383 | if (getMode() == USER_BASE || getMode() == USER_MOVEMENT_AND_BASE) { |
roysandberg | 14:73923b07ae4a | 384 | setMode(USER_MOVEMENT_AND_BASE); |
roysandberg | 14:73923b07ae4a | 385 | } else { |
roysandberg | 14:73923b07ae4a | 386 | setMode(USER_MOVEMENT); |
roysandberg | 14:73923b07ae4a | 387 | } |
roysandberg | 14:73923b07ae4a | 388 | setOverlayEffect( movement, dither, fill, effect, colorList, (int) timeConstant*100, (int) moveTimeConstant*100 ); |
roysandberg | 14:73923b07ae4a | 389 | writeToBLE("Effect set."); |
roysandberg | 14:73923b07ae4a | 390 | } else { |
roysandberg | 14:73923b07ae4a | 391 | writeToBLE("Err: Parsing."); |
roysandberg | 14:73923b07ae4a | 392 | } |
roysandberg | 14:73923b07ae4a | 393 | } else { |
roysandberg | 14:73923b07ae4a | 394 | writeToBLE("Err: Token count."); |
roysandberg | 14:73923b07ae4a | 395 | } |
roysandberg | 14:73923b07ae4a | 396 | } else if (!strcmp(tokens[0],"help") || !strcmp(tokens[0],"h")) { |
roysandberg | 14:73923b07ae4a | 397 | int hour = 1 + (TheElapsedTime / (60*60*1000)); |
roysandberg | 14:73923b07ae4a | 398 | int minute = (TheElapsedTime % (60*60*1000))/(60*1000); |
roysandberg | 14:73923b07ae4a | 399 | int second = (TheElapsedTime % (60*1000)) / 1000; |
roysandberg | 14:73923b07ae4a | 400 | sprintf(outputLine, "T:%02d:%02d:%02d,M=%d,A=%d", hour, minute, second, getMode(), lastAmplitude); |
roysandberg | 14:73923b07ae4a | 401 | writeToBLE((const uint8_t*)outputLine); |
roysandberg | 14:73923b07ae4a | 402 | wait(0.03); |
roysandberg | 14:73923b07ae4a | 403 | writeToBLE("BASE:dither,effect"); |
roysandberg | 14:73923b07ae4a | 404 | wait(0.03); |
roysandberg | 14:73923b07ae4a | 405 | writeToBLE(",color,time"); |
roysandberg | 14:73923b07ae4a | 406 | wait(0.03); |
roysandberg | 14:73923b07ae4a | 407 | writeToBLE("EFFECT:move,dither"); |
roysandberg | 14:73923b07ae4a | 408 | wait(0.03); |
roysandberg | 14:73923b07ae4a | 409 | writeToBLE(",fill,effect,color"); |
roysandberg | 14:73923b07ae4a | 410 | wait(0.03); |
roysandberg | 14:73923b07ae4a | 411 | writeToBLE(",time,moveTime"); |
roysandberg | 14:73923b07ae4a | 412 | wait(0.03); |
roysandberg | 14:73923b07ae4a | 413 | writeToBLE("MOVE:v+,v-,h+,h-,r+,"); |
roysandberg | 14:73923b07ae4a | 414 | wait(0.03); |
roysandberg | 14:73923b07ae4a | 415 | writeToBLE("r-,b+,b-,al,of"); |
roysandberg | 14:73923b07ae4a | 416 | wait(0.03); |
roysandberg | 14:73923b07ae4a | 417 | writeToBLE("DITHER:Fixed,Cross,"); |
roysandberg | 14:73923b07ae4a | 418 | wait(0.03); |
roysandberg | 14:73923b07ae4a | 419 | writeToBLE("In,Out,Strob, Puls"); |
roysandberg | 14:73923b07ae4a | 420 | wait(0.03); |
roysandberg | 14:73923b07ae4a | 421 | writeToBLE("FILL:Line,Fill"); |
roysandberg | 14:73923b07ae4a | 422 | wait(0.03); |
roysandberg | 14:73923b07ae4a | 423 | writeToBLE("EFFECT:Const,Ran"); |
roysandberg | 14:73923b07ae4a | 424 | wait(0.03); |
roysandberg | 14:73923b07ae4a | 425 | writeToBLE("Seq,Fixed"); |
roysandberg | 14:73923b07ae4a | 426 | wait(0.03); |
roysandberg | 14:73923b07ae4a | 427 | writeToBLE("COLOR:al,te,el,pa,"); |
roysandberg | 14:73923b07ae4a | 428 | wait(0.03); |
roysandberg | 14:73923b07ae4a | 429 | writeToBLE("pu,bl,gr,re,su,ye,"); |
roysandberg | 14:73923b07ae4a | 430 | wait(0.03); |
roysandberg | 14:73923b07ae4a | 431 | writeToBLE("da,go,sh"); |
roysandberg | 14:73923b07ae4a | 432 | } else { |
roysandberg | 14:73923b07ae4a | 433 | writeToBLE("Unknown command."); |
roysandberg | 14:73923b07ae4a | 434 | } |
roysandberg | 14:73923b07ae4a | 435 | |
roysandberg | 14:73923b07ae4a | 436 | for (int i=0; tokens[i] != 0;i++) { |
roysandberg | 14:73923b07ae4a | 437 | free(tokens[i]); |
roysandberg | 14:73923b07ae4a | 438 | } |
roysandberg | 14:73923b07ae4a | 439 | |
roysandberg | 14:73923b07ae4a | 440 | dataToProcess = FALSE; |
roysandberg | 14:73923b07ae4a | 441 | } |
roysandberg | 14:73923b07ae4a | 442 | |
roysandberg | 14:73923b07ae4a | 443 | void buttonHandlerAllRed() { |
roysandberg | 14:73923b07ae4a | 444 | setMode(0); |
roysandberg | 14:73923b07ae4a | 445 | for (int i=0; i< CHANNELS_PER_IC * NUMBER_OF_ICS; i++) { |
roysandberg | 14:73923b07ae4a | 446 | setChannelToRGB( (int) i, (uint16_t) allRed ? 0xFF : 0, (uint16_t) 0, (uint16_t) 0); |
roysandberg | 14:73923b07ae4a | 447 | } |
roysandberg | 14:73923b07ae4a | 448 | theChip->latchData(); |
roysandberg | 14:73923b07ae4a | 449 | printf("All red: %d\n\r",allRed); |
roysandberg | 14:73923b07ae4a | 450 | allRed = !allRed; |
roysandberg | 14:73923b07ae4a | 451 | } |
roysandberg | 14:73923b07ae4a | 452 | |
roysandberg | 14:73923b07ae4a | 453 | void buttonHandlerAllGreen() { |
roysandberg | 14:73923b07ae4a | 454 | setMode(0); |
roysandberg | 14:73923b07ae4a | 455 | for (int i=0; i< CHANNELS_PER_IC * NUMBER_OF_ICS; i++) { |
roysandberg | 14:73923b07ae4a | 456 | setChannelToRGB( (int) i, (uint16_t) 0, (uint16_t) allGreen ? 0xFF : 0, (uint16_t) 0); |
roysandberg | 14:73923b07ae4a | 457 | } |
roysandberg | 14:73923b07ae4a | 458 | theChip->latchData(); |
roysandberg | 14:73923b07ae4a | 459 | printf("All green: %d\n\r",allGreen); |
roysandberg | 14:73923b07ae4a | 460 | allGreen = !allGreen; |
roysandberg | 14:73923b07ae4a | 461 | } |
roysandberg | 14:73923b07ae4a | 462 | |
roysandberg | 14:73923b07ae4a | 463 | void buttonHandlerAllBlue() { |
roysandberg | 14:73923b07ae4a | 464 | setMode(0); |
roysandberg | 14:73923b07ae4a | 465 | for (int i=0; i< CHANNELS_PER_IC * NUMBER_OF_ICS; i++) { |
roysandberg | 14:73923b07ae4a | 466 | setChannelToRGB( (int) i, (uint16_t) 0, (uint16_t) 0, (uint16_t) allBlue ? 0xFF : 0); |
roysandberg | 14:73923b07ae4a | 467 | } |
roysandberg | 14:73923b07ae4a | 468 | theChip->latchData(); |
roysandberg | 14:73923b07ae4a | 469 | printf("All blue: %d\n\r",allBlue); |
roysandberg | 14:73923b07ae4a | 470 | allBlue = !allBlue; |
roysandberg | 14:73923b07ae4a | 471 | } |
roysandberg | 14:73923b07ae4a | 472 | |
roysandberg | 14:73923b07ae4a | 473 | void buttonHandlerMode1() { |
roysandberg | 14:73923b07ae4a | 474 | printf("Movement enabled.\n\r"); |
roysandberg | 14:73923b07ae4a | 475 | setMode(1); |
roysandberg | 14:73923b07ae4a | 476 | } |
roysandberg | 14:73923b07ae4a | 477 | |
yihui | 0:e910d9bb040f | 478 | int main(void) |
yihui | 0:e910d9bb040f | 479 | { |
roysandberg | 14:73923b07ae4a | 480 | unsigned short dotCorrect[48]; |
Rohit Grover |
2:e060367b9024 | 481 | Ticker ticker; |
roysandberg | 14:73923b07ae4a | 482 | |
roysandberg | 14:73923b07ae4a | 483 | button1.rise(&buttonHandlerAllRed); |
roysandberg | 14:73923b07ae4a | 484 | button2.rise(&buttonHandlerAllGreen); |
roysandberg | 14:73923b07ae4a | 485 | button3.rise(&buttonHandlerAllBlue); |
roysandberg | 14:73923b07ae4a | 486 | button4.rise(&buttonHandlerMode1); |
roysandberg | 14:73923b07ae4a | 487 | |
roysandberg | 14:73923b07ae4a | 488 | // Set dot correct to maximum brightness for all channels |
roysandberg | 14:73923b07ae4a | 489 | for (int i=0;i<48;i++) { |
roysandberg | 14:73923b07ae4a | 490 | dotCorrect[i] = 0x7F; |
roysandberg | 14:73923b07ae4a | 491 | } |
roysandberg | 14:73923b07ae4a | 492 | |
roysandberg | 14:73923b07ae4a | 493 | // SCLK = P0_1, MOSI = P0_2, GSCLK = P0_3, LAT = P0_4 |
roysandberg | 14:73923b07ae4a | 494 | theChip = new TLC5955(P0_1, P0_2, P0_3, P0_4); |
roysandberg | 14:73923b07ae4a | 495 | |
roysandberg | 14:73923b07ae4a | 496 | |
roysandberg | 14:73923b07ae4a | 497 | |
roysandberg | 14:73923b07ae4a | 498 | wait(0.01); |
roysandberg | 14:73923b07ae4a | 499 | |
roysandberg | 14:73923b07ae4a | 500 | // Initial settings |
roysandberg | 14:73923b07ae4a | 501 | |
roysandberg | 14:73923b07ae4a | 502 | theChip->setNewControlData(0x7F, 0x7F, 0x7F, // global brightness set to max for R, G, and B channels |
roysandberg | 14:73923b07ae4a | 503 | TLC5955::I_3_2_MA, TLC5955::I_3_2_MA, TLC5955::I_3_2_MA, // maximum current set to 3.2mA for R, G, and B channels |
roysandberg | 14:73923b07ae4a | 504 | dotCorrect); |
roysandberg | 14:73923b07ae4a | 505 | |
roysandberg | 14:73923b07ae4a | 506 | wait(0.01); |
roysandberg | 14:73923b07ae4a | 507 | |
roysandberg | 14:73923b07ae4a | 508 | theChip->latchData(); // set all channels to zero, which is the default |
roysandberg | 14:73923b07ae4a | 509 | |
roysandberg | 14:73923b07ae4a | 510 | DEBUG("\n\r\n\rTLC5955 Reset.\n\r"); |
roysandberg | 14:73923b07ae4a | 511 | |
roysandberg | 14:73923b07ae4a | 512 | SequencerConfig(); |
roysandberg | 14:73923b07ae4a | 513 | |
roysandberg | 14:73923b07ae4a | 514 | ticker.attach(periodicCallback, SEQUENCER_RATE); |
roysandberg | 14:73923b07ae4a | 515 | |
roysandberg | 14:73923b07ae4a | 516 | // In case setup takes some amount of time, we're doing it after we turn off the LEDs. |
roysandberg | 14:73923b07ae4a | 517 | ble = new BLEDevice(); |
yihui | 0:e910d9bb040f | 518 | |
Rohit Grover |
2:e060367b9024 | 519 | DEBUG("Initialising the nRF51822\n\r"); |
roysandberg | 14:73923b07ae4a | 520 | ble->init(); |
roysandberg | 14:73923b07ae4a | 521 | ble->onDisconnection(disconnectionCallback); |
roysandberg | 14:73923b07ae4a | 522 | ble->onConnection(connectCallback); |
roysandberg | 14:73923b07ae4a | 523 | ble->onDataWritten(onDataWritten); |
yihui | 0:e910d9bb040f | 524 | |
Rohit Grover |
2:e060367b9024 | 525 | /* setup advertising */ |
roysandberg | 14:73923b07ae4a | 526 | ble->accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED); |
roysandberg | 14:73923b07ae4a | 527 | ble->setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); |
roysandberg | 14:73923b07ae4a | 528 | ble->accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, |
roysandberg | 14:73923b07ae4a | 529 | (const uint8_t *)"DuckLights", sizeof("DuckLights") - 1); |
roysandberg | 14:73923b07ae4a | 530 | ble->accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, |
rgrover1 | 6:e0fc9072e853 | 531 | (const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed)); |
yihui | 0:e910d9bb040f | 532 | |
roysandberg | 14:73923b07ae4a | 533 | ble->setAdvertisingInterval(1000); /* 1000ms; in multiples of 0.625ms. */ |
roysandberg | 14:73923b07ae4a | 534 | ble->startAdvertising(); |
yihui | 0:e910d9bb040f | 535 | |
roysandberg | 14:73923b07ae4a | 536 | UARTService uartService(*ble); |
rgrover1 | 6:e0fc9072e853 | 537 | uartServicePtr = &uartService; |
yihui | 0:e910d9bb040f | 538 | |
roysandberg | 14:73923b07ae4a | 539 | DEBUG("Entering infinite loop.\n\r"); |
roysandberg | 14:73923b07ae4a | 540 | |
Rohit Grover |
2:e060367b9024 | 541 | while (true) { |
roysandberg | 14:73923b07ae4a | 542 | ble->waitForEvent(); |
roysandberg | 14:73923b07ae4a | 543 | if (dataToProcess) { |
roysandberg | 14:73923b07ae4a | 544 | parseInputData(); |
roysandberg | 14:73923b07ae4a | 545 | } |
yihui | 0:e910d9bb040f | 546 | } |
yihui | 0:e910d9bb040f | 547 | } |