Published

Dependencies:   BLE_API TLC5955 mbed nRF51822

Fork of BLE_LoopbackUART by Bluetooth Low Energy

Committer:
roysandberg
Date:
Sat Jun 09 23:23:06 2018 +0000
Revision:
14:73923b07ae4a
Parent:
13:15764cc1f12c
Published

Who changed what in which revision?

UserRevisionLine numberNew 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 }