Demo starter application to connect WiGo to NSP and expose on-board sensors

Dependencies:   NVIC_set_all_priorities cc3000_hostdriver_mbedsocket mbed nsdl_lib TEMT6200 TSI Wi-Go_eCompass_Lib_V3 WiGo_BattCharger

This is the mbed project for the IoT World Hackathon event, June 17th and 18th in Palo Also.

The setup instructions for participants are at the Setup page of this wiki:

http://mbed.org/teams/MBED_DEMOS/code/IoT_World_Hackathon_WiGo_NSP_Demo/wiki/Setup-Guide-for-the-IoT-World-Hackathon

Committer:
sam_grove
Date:
Wed Jun 18 03:29:01 2014 +0000
Revision:
16:d6812604cf92
Parent:
4:727f1aeb717a
Changed comport to 9600 baud (default for nearly all terminals); Moved UDPSocket and Endpoint to main (extern in nsdl); Added heap checking and hard fault handler; Don't register the Magnetometer

Who changed what in which revision?

UserRevisionLine numberNew contents of line
michaeljkoster 0:07581223f90c 1 /* mbed Microcontroller Library
michaeljkoster 0:07581223f90c 2 * Copyright (c) 2006-2013 ARM Limited
michaeljkoster 0:07581223f90c 3 *
michaeljkoster 0:07581223f90c 4 * Licensed under the Apache License, Version 2.0 (the "License");
michaeljkoster 0:07581223f90c 5 * you may not use this file except in compliance with the License.
michaeljkoster 0:07581223f90c 6 * You may obtain a copy of the License at
michaeljkoster 0:07581223f90c 7 *
michaeljkoster 0:07581223f90c 8 * http://www.apache.org/licenses/LICENSE-2.0
michaeljkoster 0:07581223f90c 9 *
michaeljkoster 0:07581223f90c 10 * Unless required by applicable law or agreed to in writing, software
michaeljkoster 0:07581223f90c 11 * distributed under the License is distributed on an "AS IS" BASIS,
michaeljkoster 0:07581223f90c 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
michaeljkoster 0:07581223f90c 13 * See the License for the specific language governing permissions and
michaeljkoster 0:07581223f90c 14 * limitations under the License.
michaeljkoster 0:07581223f90c 15 */
michaeljkoster 0:07581223f90c 16 #include "mbed.h"
michaeljkoster 0:07581223f90c 17 #include "cc3000.h"
michaeljkoster 0:07581223f90c 18 #include "main.h"
sam_grove 16:d6812604cf92 19 #include "UDPSocket.h"
michaeljkoster 0:07581223f90c 20 #include "TCPSocketConnection.h"
michaeljkoster 0:07581223f90c 21 #include "TCPSocketServer.h"
michaeljkoster 0:07581223f90c 22 #include "nsdl_support.h"
michaeljkoster 0:07581223f90c 23
michaeljkoster 0:07581223f90c 24 using namespace mbed_cc3000;
michaeljkoster 0:07581223f90c 25
michaeljkoster 0:07581223f90c 26 tUserFS user_info;
michaeljkoster 0:07581223f90c 27
michaeljkoster 0:07581223f90c 28 /* cc3000 module declaration specific for user's board. Check also init() */
michaeljkoster 0:07581223f90c 29 #if (MY_BOARD == WIGO)
michaeljkoster 0:07581223f90c 30
michaeljkoster 0:07581223f90c 31 #include "I2C_busreset.h"
michaeljkoster 0:07581223f90c 32 #include "defLED.h"
michaeljkoster 0:07581223f90c 33 #include "TSISensor.h"
michaeljkoster 0:07581223f90c 34 #include "TEMT6200.h"
michaeljkoster 0:07581223f90c 35 #include "WiGo_BattCharger.h"
michaeljkoster 0:07581223f90c 36 #include "MMA8451Q.h"
michaeljkoster 0:07581223f90c 37 #include "MAG3110.h"
michaeljkoster 0:07581223f90c 38 #include "MPL3115A2.h"
michaeljkoster 0:07581223f90c 39 #include "Wi-Go_eCompass_Lib_V3.h"
michaeljkoster 0:07581223f90c 40 #include "demo.h"
michaeljkoster 0:07581223f90c 41 #include "doTCPIP.h"
michaeljkoster 0:07581223f90c 42 #include "run_exosite.h"
michaeljkoster 0:07581223f90c 43
michaeljkoster 0:07581223f90c 44 #define FCOUNTSPERG 4096.0F // sensor specific: MMA8451 provide 4096 counts / g in 2g mode
michaeljkoster 0:07581223f90c 45 #define FCOUNTSPERUT 10.0F // sensor specific: MAG3110 provide 10 counts / uT
michaeljkoster 0:07581223f90c 46
michaeljkoster 0:07581223f90c 47 #define BATT_0 0.53
michaeljkoster 0:07581223f90c 48 #define BATT_100 0.63
michaeljkoster 0:07581223f90c 49
michaeljkoster 0:07581223f90c 50 DigitalOut ledr (LED_RED);
michaeljkoster 0:07581223f90c 51 DigitalOut ledg (LED_GREEN);
michaeljkoster 0:07581223f90c 52 DigitalOut ledb (LED_BLUE);
michaeljkoster 0:07581223f90c 53 DigitalOut led1 (PTB8);
michaeljkoster 0:07581223f90c 54 DigitalOut led2 (PTB9);
michaeljkoster 0:07581223f90c 55 DigitalOut led3 (PTB10);
michaeljkoster 0:07581223f90c 56
michaeljkoster 0:07581223f90c 57 cc3000 wifi(PTA16, PTA13, PTD0, SPI(PTD2, PTD3, PTC5), "", "", NONE, true);
michaeljkoster 0:07581223f90c 58
michaeljkoster 0:07581223f90c 59 TCPSocketConnection socket;
michaeljkoster 0:07581223f90c 60
sam_grove 16:d6812604cf92 61 UDPSocket server;
sam_grove 16:d6812604cf92 62 Endpoint nsp;
sam_grove 16:d6812604cf92 63
sam_grove 16:d6812604cf92 64 #define MEM_VALID(x) \
sam_grove 16:d6812604cf92 65 int s##x=0;\
sam_grove 16:d6812604cf92 66 int *h##x = new int [1];\
sam_grove 16:d6812604cf92 67 std::printf("[stack]0x%08x\t[heap]0x%08x\t[memory avail]%d bytes \tLine: %d %s\r\n", &s##x, h##x, &s##x-h##x, __LINE__, __FILE__);\
sam_grove 16:d6812604cf92 68 if (h##x > &s##x)\
sam_grove 16:d6812604cf92 69 printf("collision\n");\
sam_grove 16:d6812604cf92 70 else\
sam_grove 16:d6812604cf92 71 delete [] h##x;\
sam_grove 16:d6812604cf92 72 __nop()
sam_grove 16:d6812604cf92 73
sam_grove 16:d6812604cf92 74 extern "C" void HardFault_Handler(void){MEM_VALID(0); printf("hard faulted - doh!\r\n"); while(1);}
sam_grove 16:d6812604cf92 75
michaeljkoster 0:07581223f90c 76 Serial pc(USBTX, USBRX);
michaeljkoster 0:07581223f90c 77
michaeljkoster 0:07581223f90c 78 // Slide sensor
michaeljkoster 0:07581223f90c 79 TSISensor tsi;
michaeljkoster 0:07581223f90c 80
michaeljkoster 0:07581223f90c 81 // Systick
michaeljkoster 0:07581223f90c 82 Ticker systick;
michaeljkoster 0:07581223f90c 83
michaeljkoster 0:07581223f90c 84 // Ambient light sensor : PTD5 = enable, PTB0 = analog input
michaeljkoster 0:07581223f90c 85 TEMT6200 ambi(PTD5, PTB0);
michaeljkoster 0:07581223f90c 86
michaeljkoster 0:07581223f90c 87 //Wi-Go battery charger control
michaeljkoster 0:07581223f90c 88 WiGo_BattCharger Batt(CHRG_EN1, CHRG_EN2, CHRG_SNS_EN, CHRG_SNS, CHRG_POK, CHRG_CHG);
michaeljkoster 0:07581223f90c 89
michaeljkoster 0:07581223f90c 90 // Accelerometer
michaeljkoster 0:07581223f90c 91 #define MMA8451_I2C_ADDRESS (0x1d<<1)
michaeljkoster 0:07581223f90c 92 MMA8451Q acc(PTE25, PTE24, MMA8451_I2C_ADDRESS);
michaeljkoster 0:07581223f90c 93
michaeljkoster 0:07581223f90c 94 // Magnetometer
michaeljkoster 0:07581223f90c 95 #define MAG3110_I2C_ADDRESS (0x0e<<1)
michaeljkoster 0:07581223f90c 96 MAG3110 mag(PTE0, PTE1, MAG3110_I2C_ADDRESS);
michaeljkoster 0:07581223f90c 97
michaeljkoster 0:07581223f90c 98 // altimeter-Pressure-Temperature (apt)
michaeljkoster 0:07581223f90c 99 #define MPL3115A2_I2C_ADDRESS (0x60<<1)
michaeljkoster 0:07581223f90c 100 MPL3115A2 apt( PTE0, PTE1, MPL3115A2_I2C_ADDRESS);
michaeljkoster 0:07581223f90c 101
michaeljkoster 0:07581223f90c 102 volatile int secondFlag;
michaeljkoster 0:07581223f90c 103 volatile int HsecondFlag;
michaeljkoster 0:07581223f90c 104 unsigned int seconds;
michaeljkoster 0:07581223f90c 105 unsigned int compass_type;
michaeljkoster 0:07581223f90c 106 unsigned short adc_sample3;
michaeljkoster 0:07581223f90c 107 float fcountperg = 1.0F / FCOUNTSPERG;
michaeljkoster 0:07581223f90c 108 float fcountperut = 1.0F / FCOUNTSPERUT;
michaeljkoster 0:07581223f90c 109 volatile unsigned char newData;
michaeljkoster 0:07581223f90c 110 volatile int server_running;
michaeljkoster 0:07581223f90c 111 axis6_t axis6;
michaeljkoster 0:07581223f90c 112 int do_mDNS = 0;
michaeljkoster 0:07581223f90c 113 //Device name - used for Smart config in order to stop the Smart phone configuration process
michaeljkoster 0:07581223f90c 114 char DevServname[] = "CC3000";
michaeljkoster 0:07581223f90c 115
michaeljkoster 0:07581223f90c 116 void initLEDs(void)
michaeljkoster 0:07581223f90c 117 {
michaeljkoster 0:07581223f90c 118 RED_OFF;
michaeljkoster 0:07581223f90c 119 GREEN_OFF;
michaeljkoster 0:07581223f90c 120 BLUE_OFF;
michaeljkoster 0:07581223f90c 121 LED_D1_OFF;
michaeljkoster 0:07581223f90c 122 LED_D2_OFF;
michaeljkoster 0:07581223f90c 123 LED_D3_OFF;
michaeljkoster 0:07581223f90c 124 }
michaeljkoster 0:07581223f90c 125
michaeljkoster 0:07581223f90c 126 void GreenStop(void)
michaeljkoster 0:07581223f90c 127 {
michaeljkoster 0:07581223f90c 128 RED_OFF; GREEN_OFF; BLUE_OFF;
michaeljkoster 0:07581223f90c 129 while(1)
michaeljkoster 0:07581223f90c 130 {
michaeljkoster 0:07581223f90c 131 GREEN_ON;
michaeljkoster 0:07581223f90c 132 secondFlag = 0;
michaeljkoster 0:07581223f90c 133 while(!secondFlag);
michaeljkoster 0:07581223f90c 134 GREEN_OFF;
michaeljkoster 0:07581223f90c 135 secondFlag = 0;
michaeljkoster 0:07581223f90c 136 while(!secondFlag);
michaeljkoster 0:07581223f90c 137 }
michaeljkoster 0:07581223f90c 138 }
michaeljkoster 0:07581223f90c 139
michaeljkoster 0:07581223f90c 140 void accel_read(void)
michaeljkoster 0:07581223f90c 141 {
michaeljkoster 0:07581223f90c 142 signed short resultx, resulty, resultz;
michaeljkoster 0:07581223f90c 143 if(acc.isDataAvailable())
michaeljkoster 0:07581223f90c 144 {
michaeljkoster 0:07581223f90c 145 resultx = acc.readReg(0x01)<<8;
michaeljkoster 0:07581223f90c 146 resultx |= acc.readReg(0x02);
michaeljkoster 0:07581223f90c 147 resultx = resultx >> 2;
michaeljkoster 0:07581223f90c 148 resulty = acc.readReg(0x03)<<8;
michaeljkoster 0:07581223f90c 149 resulty |= acc.readReg(0x04);
michaeljkoster 0:07581223f90c 150 resulty = resulty >> 2;
michaeljkoster 0:07581223f90c 151 resultz = acc.readReg(0x05)<<8;
michaeljkoster 0:07581223f90c 152 resultz |= acc.readReg(0x06);
michaeljkoster 0:07581223f90c 153 resultz = resultz >> 2;
michaeljkoster 0:07581223f90c 154 if(compass_type == NED_COMPASS)
michaeljkoster 0:07581223f90c 155 {
michaeljkoster 0:07581223f90c 156 axis6.acc_x = resultx;
michaeljkoster 0:07581223f90c 157 axis6.acc_y = -1 * resulty; // multiple by -1 to compensate for PCB layout
michaeljkoster 0:07581223f90c 158 axis6.acc_z = resultz;
michaeljkoster 0:07581223f90c 159 }
michaeljkoster 0:07581223f90c 160 if(compass_type == ANDROID_COMPASS)
michaeljkoster 0:07581223f90c 161 {
michaeljkoster 0:07581223f90c 162 axis6.acc_x = resulty; //
michaeljkoster 0:07581223f90c 163 axis6.acc_y = -1 * resultx;
michaeljkoster 0:07581223f90c 164 axis6.acc_z = resultz;
michaeljkoster 0:07581223f90c 165 }
michaeljkoster 0:07581223f90c 166 if(compass_type == WINDOWS_COMPASS)
michaeljkoster 0:07581223f90c 167 {
michaeljkoster 0:07581223f90c 168 axis6.acc_x = -1 * resulty; //
michaeljkoster 0:07581223f90c 169 axis6.acc_y = resultx;
michaeljkoster 0:07581223f90c 170 axis6.acc_z = resultz;
michaeljkoster 0:07581223f90c 171 }
michaeljkoster 0:07581223f90c 172 axis6.fax = axis6.acc_x;
michaeljkoster 0:07581223f90c 173 axis6.fay = axis6.acc_y;
michaeljkoster 0:07581223f90c 174 axis6.faz = axis6.acc_z;
michaeljkoster 0:07581223f90c 175 axis6.fGax = axis6.fax * fcountperg;
michaeljkoster 0:07581223f90c 176 axis6.fGay = axis6.fay * fcountperg;
michaeljkoster 0:07581223f90c 177 axis6.fGaz = axis6.faz * fcountperg;
michaeljkoster 0:07581223f90c 178 }
michaeljkoster 0:07581223f90c 179 }
michaeljkoster 0:07581223f90c 180
michaeljkoster 0:07581223f90c 181 void readTempAlt(void) // We don't use the fractional data
michaeljkoster 0:07581223f90c 182 {
michaeljkoster 0:07581223f90c 183 unsigned char raw_data[2];
michaeljkoster 0:07581223f90c 184 if(apt.getAltimeterRaw(&raw_data[0]))
michaeljkoster 0:07581223f90c 185 axis6.alt = ((raw_data[0] << 8) | raw_data[1]);
michaeljkoster 0:07581223f90c 186 if(apt.getTemperatureRaw(&raw_data[0]))
michaeljkoster 0:07581223f90c 187 axis6.temp = raw_data[0];
michaeljkoster 0:07581223f90c 188 }
michaeljkoster 0:07581223f90c 189
michaeljkoster 0:07581223f90c 190 void readCompass( void )
michaeljkoster 0:07581223f90c 191 {
michaeljkoster 0:07581223f90c 192 if(mag.isDataAvailable())
michaeljkoster 0:07581223f90c 193 {
michaeljkoster 0:07581223f90c 194 uint8_t mx_msb, my_msb, mz_msb;
michaeljkoster 0:07581223f90c 195 uint8_t mx_lsb, my_lsb, mz_lsb;
michaeljkoster 0:07581223f90c 196
michaeljkoster 0:07581223f90c 197 mx_msb = mag.readReg(0x01);
michaeljkoster 0:07581223f90c 198 mx_lsb = mag.readReg(0x02);
michaeljkoster 0:07581223f90c 199 my_msb = mag.readReg(0x03);
michaeljkoster 0:07581223f90c 200 my_lsb = mag.readReg(0x04);
michaeljkoster 0:07581223f90c 201 mz_msb = mag.readReg(0x05);
michaeljkoster 0:07581223f90c 202 mz_lsb = mag.readReg(0x06);
michaeljkoster 0:07581223f90c 203
michaeljkoster 0:07581223f90c 204 if(compass_type == NED_COMPASS)
michaeljkoster 0:07581223f90c 205 {
michaeljkoster 0:07581223f90c 206 axis6.mag_y = (((mx_msb << 8) | mx_lsb)); // x & y swapped to compensate for PCB layout
michaeljkoster 0:07581223f90c 207 axis6.mag_x = (((my_msb << 8) | my_lsb));
michaeljkoster 0:07581223f90c 208 axis6.mag_z = (((mz_msb << 8) | mz_lsb));
michaeljkoster 0:07581223f90c 209 }
michaeljkoster 0:07581223f90c 210 if(compass_type == ANDROID_COMPASS)
michaeljkoster 0:07581223f90c 211 {
michaeljkoster 0:07581223f90c 212 axis6.mag_x = (((mx_msb << 8) | mx_lsb));
michaeljkoster 0:07581223f90c 213 axis6.mag_y = (((my_msb << 8) | my_lsb));
michaeljkoster 0:07581223f90c 214 axis6.mag_z = -1 * (((mz_msb << 8) | mz_lsb)); // negate to reverse axis of Z to conform to Android coordinate system
michaeljkoster 0:07581223f90c 215 }
michaeljkoster 0:07581223f90c 216 if(compass_type == WINDOWS_COMPASS)
michaeljkoster 0:07581223f90c 217 {
michaeljkoster 0:07581223f90c 218 axis6.mag_x = (((mx_msb << 8) | mx_lsb));
michaeljkoster 0:07581223f90c 219 axis6.mag_y = (((my_msb << 8) | my_lsb));
michaeljkoster 0:07581223f90c 220 axis6.mag_z = -1 * (((mz_msb << 8) | mz_lsb));
michaeljkoster 0:07581223f90c 221 }
michaeljkoster 0:07581223f90c 222 axis6.fmx = axis6.mag_x;
michaeljkoster 0:07581223f90c 223 axis6.fmy = axis6.mag_y;
michaeljkoster 0:07581223f90c 224 axis6.fmz = axis6.mag_z;
michaeljkoster 0:07581223f90c 225 axis6.fUTmx = axis6.fmx * fcountperut;
michaeljkoster 0:07581223f90c 226 axis6.fUTmy = axis6.fmy * fcountperut;
michaeljkoster 0:07581223f90c 227 axis6.fUTmz = axis6.fmz * fcountperut;
michaeljkoster 0:07581223f90c 228 }
michaeljkoster 0:07581223f90c 229 }
michaeljkoster 0:07581223f90c 230
michaeljkoster 0:07581223f90c 231 void axis6Print(void)
michaeljkoster 0:07581223f90c 232 {
michaeljkoster 0:07581223f90c 233 char *compass_points[9] = {"North", "N-East", "East", "S-East", "South", "S-West", "West", "N-West", "North"};
michaeljkoster 0:07581223f90c 234 signed short compass_bearing = (axis6.compass + 23) / 45;
michaeljkoster 0:07581223f90c 235 printf("Compass : Roll=%-d Pitch=%-d Yaw=%-d [%s]\r\n", axis6.roll, axis6.pitch, axis6.yaw, compass_points[compass_bearing]);
michaeljkoster 0:07581223f90c 236 printf("Accel : X= %1.2f, Y= %1.2f, Z= %1.2f\r\n", axis6.fGax, axis6.fGay, axis6.fGaz);
michaeljkoster 0:07581223f90c 237 printf("Magneto : X= %3.1f, Y= %3.1f, Z= %3.1f\r\n\r\n", axis6.fUTmx, axis6.fUTmy, axis6.fUTmz);
michaeljkoster 0:07581223f90c 238 }
michaeljkoster 0:07581223f90c 239
michaeljkoster 0:07581223f90c 240 void set_dir_LED(void)
michaeljkoster 0:07581223f90c 241 {
michaeljkoster 0:07581223f90c 242 RED_OFF; GREEN_OFF; BLUE_OFF;
michaeljkoster 0:07581223f90c 243
michaeljkoster 0:07581223f90c 244 if((axis6.compass >= 353) || (axis6.compass <= 7))
michaeljkoster 0:07581223f90c 245 {
michaeljkoster 0:07581223f90c 246 GREEN_ON;
michaeljkoster 0:07581223f90c 247 }
michaeljkoster 0:07581223f90c 248 else
michaeljkoster 0:07581223f90c 249 {
michaeljkoster 0:07581223f90c 250 GREEN_OFF;
michaeljkoster 0:07581223f90c 251 }
michaeljkoster 0:07581223f90c 252 if(((axis6.compass >= 348) && (axis6.compass <= 357)) || ((axis6.compass >= 3) && (axis6.compass <= 12)))
michaeljkoster 0:07581223f90c 253 {
michaeljkoster 0:07581223f90c 254 BLUE_ON;
michaeljkoster 0:07581223f90c 255 }
michaeljkoster 0:07581223f90c 256 else
michaeljkoster 0:07581223f90c 257 {
michaeljkoster 0:07581223f90c 258 BLUE_OFF;
michaeljkoster 0:07581223f90c 259 }
michaeljkoster 0:07581223f90c 260 if((axis6.compass >= 348) || (axis6.compass <= 12)) return;
michaeljkoster 0:07581223f90c 261 if(((axis6.compass >= 268) && (axis6.compass <= 272)) || ((axis6.compass >= 88) && (axis6.compass <= 92)))
michaeljkoster 0:07581223f90c 262 {
michaeljkoster 0:07581223f90c 263 RED_ON;
michaeljkoster 0:07581223f90c 264 return;
michaeljkoster 0:07581223f90c 265 }
michaeljkoster 0:07581223f90c 266 if((axis6.compass >= 178) && (axis6.compass <= 182))
michaeljkoster 0:07581223f90c 267 {
michaeljkoster 0:07581223f90c 268 BLUE_ON;
michaeljkoster 0:07581223f90c 269 RED_ON;
michaeljkoster 0:07581223f90c 270 return;
michaeljkoster 0:07581223f90c 271 }
michaeljkoster 0:07581223f90c 272 }
michaeljkoster 0:07581223f90c 273
michaeljkoster 0:07581223f90c 274 void SysTick_Handler(void)
michaeljkoster 0:07581223f90c 275 {
michaeljkoster 0:07581223f90c 276 static unsigned int ttt = 1;
michaeljkoster 0:07581223f90c 277 int ts;
michaeljkoster 0:07581223f90c 278 ts = ttt & 0x1;
michaeljkoster 0:07581223f90c 279 if(ts == 0)
michaeljkoster 0:07581223f90c 280 {
michaeljkoster 0:07581223f90c 281 accel_read();
michaeljkoster 0:07581223f90c 282 readCompass();
michaeljkoster 0:07581223f90c 283 }
michaeljkoster 0:07581223f90c 284 if(ts == 1)
michaeljkoster 0:07581223f90c 285 {
michaeljkoster 0:07581223f90c 286 run_eCompass();
michaeljkoster 0:07581223f90c 287 newData = 1; // a general purpose flag for things that need to synch to the ISR
michaeljkoster 0:07581223f90c 288 axis6.timestamp++;
michaeljkoster 0:07581223f90c 289 if(!server_running) set_dir_LED(); // Set the LEDs based on direction when nothing else is usng them
michaeljkoster 0:07581223f90c 290 }
michaeljkoster 0:07581223f90c 291 if(ttt == 50)
michaeljkoster 0:07581223f90c 292 {
michaeljkoster 0:07581223f90c 293 LED_D1_ON;
michaeljkoster 0:07581223f90c 294 if(seconds && (seconds < 15)) calibrate_eCompass();
michaeljkoster 0:07581223f90c 295 readTempAlt();
michaeljkoster 0:07581223f90c 296 axis6.light = ambi.readRaw(); // Light Sensor
michaeljkoster 0:07581223f90c 297 HsecondFlag = 1; // A general purpose flag for things that need to happen every 500ms
michaeljkoster 0:07581223f90c 298 }
michaeljkoster 0:07581223f90c 299 if(ttt >= 100)
michaeljkoster 0:07581223f90c 300 {
michaeljkoster 0:07581223f90c 301 LED_D1_OFF;
michaeljkoster 0:07581223f90c 302 ttt = 1;
michaeljkoster 0:07581223f90c 303 calibrate_eCompass();
michaeljkoster 0:07581223f90c 304 Batt.sense_en(1);
michaeljkoster 0:07581223f90c 305 adc_sample3 = Batt.level();
michaeljkoster 0:07581223f90c 306 Batt.sense_en(0);
michaeljkoster 0:07581223f90c 307 secondFlag = 1; // A general purpose flag for things that need to happen once a second
michaeljkoster 0:07581223f90c 308 HsecondFlag = 1;
michaeljkoster 0:07581223f90c 309 seconds++;
michaeljkoster 0:07581223f90c 310 if(!(seconds & 0x1F)) do_mDNS = 1;
michaeljkoster 0:07581223f90c 311 } else ttt++;
michaeljkoster 0:07581223f90c 312 }
michaeljkoster 0:07581223f90c 313 /*void SysTick_Handler(void)
michaeljkoster 0:07581223f90c 314 {
michaeljkoster 0:07581223f90c 315 static unsigned int ttt = 1;
michaeljkoster 0:07581223f90c 316 int ts;
michaeljkoster 0:07581223f90c 317 ts = ttt & 0x3;
michaeljkoster 0:07581223f90c 318 if(ts == 2) readCompass();
michaeljkoster 0:07581223f90c 319 if(ts == 1) accel_read();
michaeljkoster 0:07581223f90c 320 if(ts == 3)
michaeljkoster 0:07581223f90c 321 {
michaeljkoster 0:07581223f90c 322 run_eCompass();
michaeljkoster 0:07581223f90c 323 newData = 1; // a general purpose flag for things that need to synch to the ISR
michaeljkoster 0:07581223f90c 324 axis6.timestamp++;
michaeljkoster 0:07581223f90c 325 if(!server_running) set_dir_LED(); // Set the LEDs based on direction when nothing else is usng them
michaeljkoster 0:07581223f90c 326 }
michaeljkoster 0:07581223f90c 327 if(ttt == 100)//systick = 0.005 : 100 - systick = 0.025 : 20
michaeljkoster 0:07581223f90c 328 {
michaeljkoster 0:07581223f90c 329 LED_D1_ON;
michaeljkoster 0:07581223f90c 330 if(seconds && (seconds < 15)) calibrate_eCompass();
michaeljkoster 0:07581223f90c 331 readTempAlt();
michaeljkoster 0:07581223f90c 332 axis6.light = ambi.readRaw(); // Light Sensor
michaeljkoster 0:07581223f90c 333 HsecondFlag = 1; // A general purpose flag for things that need to happen every 500ms
michaeljkoster 0:07581223f90c 334 }
michaeljkoster 0:07581223f90c 335 if(ttt >= 200)//systick = 0.005 : 200 - systick = 0.025 : 40
michaeljkoster 0:07581223f90c 336 {
michaeljkoster 0:07581223f90c 337 LED_D1_OFF;
michaeljkoster 0:07581223f90c 338 ttt = 1;
michaeljkoster 0:07581223f90c 339 calibrate_eCompass();
michaeljkoster 0:07581223f90c 340 Batt.sense_en(1);
michaeljkoster 0:07581223f90c 341 adc_sample3 = Batt.level();
michaeljkoster 0:07581223f90c 342 Batt.sense_en(0);
michaeljkoster 0:07581223f90c 343 secondFlag = 1; // A general purpose flag for things that need to happen once a second
michaeljkoster 0:07581223f90c 344 HsecondFlag = 1;
michaeljkoster 0:07581223f90c 345 seconds++;
michaeljkoster 0:07581223f90c 346 if(!(seconds & 0x1F)) do_mDNS = 1;
michaeljkoster 0:07581223f90c 347 } else ttt++;
michaeljkoster 0:07581223f90c 348 }*/
michaeljkoster 0:07581223f90c 349
michaeljkoster 0:07581223f90c 350 #elif (MY_BOARD == WIFI_DIPCORTEX)
michaeljkoster 0:07581223f90c 351 cc3000 wifi(p28, p27, p30, SPI(p21, p14, p37), PIN_INT0_IRQn);
michaeljkoster 0:07581223f90c 352 Serial pc(UART_TX, UART_RX);
michaeljkoster 0:07581223f90c 353 #else
michaeljkoster 0:07581223f90c 354
michaeljkoster 0:07581223f90c 355 #endif
michaeljkoster 0:07581223f90c 356
michaeljkoster 0:07581223f90c 357 #ifndef CC3000_UNENCRYPTED_SMART_CONFIG
michaeljkoster 0:07581223f90c 358 const uint8_t smartconfigkey[] = {0x73,0x6d,0x61,0x72,0x74,0x63,0x6f,0x6e,0x66,0x69,0x67,0x41,0x45,0x53,0x31,0x36};
michaeljkoster 0:07581223f90c 359 #else
michaeljkoster 0:07581223f90c 360 const uint8_t smartconfigkey = 0;
michaeljkoster 0:07581223f90c 361 #endif
michaeljkoster 0:07581223f90c 362
michaeljkoster 0:07581223f90c 363 /**
michaeljkoster 0:07581223f90c 364 * \brief Print cc3000 information
michaeljkoster 0:07581223f90c 365 * \param none
michaeljkoster 0:07581223f90c 366 * \return none
michaeljkoster 0:07581223f90c 367 */
michaeljkoster 0:07581223f90c 368 void print_cc3000_info() {
michaeljkoster 0:07581223f90c 369 uint8_t myMAC[8];
michaeljkoster 0:07581223f90c 370 uint8_t spVER[5];
michaeljkoster 0:07581223f90c 371 wifi._nvmem.read_sp_version(spVER);
michaeljkoster 0:07581223f90c 372 printf("SP Version (TI) : %d %d %d %d %d\r\n", spVER[0], spVER[1], spVER[2], spVER[3], spVER[4]);
michaeljkoster 0:07581223f90c 373 printf("MAC address + cc3000 info \r\n");
michaeljkoster 0:07581223f90c 374 wifi.get_user_file_info((uint8_t *)&user_info, sizeof(user_info));
michaeljkoster 0:07581223f90c 375 wifi.get_mac_address(myMAC);
michaeljkoster 0:07581223f90c 376 printf(" MAC address %02x:%02x:%02x:%02x:%02x:%02x \r\n \r\n", myMAC[0], myMAC[1], myMAC[2], myMAC[3], myMAC[4], myMAC[5]);
michaeljkoster 0:07581223f90c 377
michaeljkoster 0:07581223f90c 378 printf(" FTC %i \r\n",user_info.FTC);
michaeljkoster 0:07581223f90c 379 printf(" PP_version %i.%i \r\n",user_info.PP_version[0], user_info.PP_version[1]);
michaeljkoster 0:07581223f90c 380 printf(" SERV_PACK %i.%i \r\n",user_info.SERV_PACK[0], user_info.SERV_PACK[1]);
michaeljkoster 0:07581223f90c 381 printf(" DRV_VER %i.%i.%i \r\n",user_info.DRV_VER[0], user_info.DRV_VER[1], user_info.DRV_VER[2]);
michaeljkoster 0:07581223f90c 382 printf(" FW_VER %i.%i.%i \r\n",user_info.FW_VER[0], user_info.FW_VER[1], user_info.FW_VER[2]);
michaeljkoster 0:07581223f90c 383 }
michaeljkoster 0:07581223f90c 384
michaeljkoster 0:07581223f90c 385 /**
michaeljkoster 0:07581223f90c 386 * \brief Connect to SSID with a timeout
michaeljkoster 0:07581223f90c 387 * \param ssid Name of SSID
michaeljkoster 0:07581223f90c 388 * \param key Password
michaeljkoster 0:07581223f90c 389 * \param sec_mode Security mode
michaeljkoster 0:07581223f90c 390 * \return none
michaeljkoster 0:07581223f90c 391 */
michaeljkoster 0:07581223f90c 392 void connect_to_ssid(char *ssid, char *key, unsigned char sec_mode) {
michaeljkoster 0:07581223f90c 393 printf("Connecting to SSID: %s. Timeout is 10s. \r\n",ssid);
michaeljkoster 0:07581223f90c 394 if (wifi.connect_to_AP((uint8_t *)ssid, (uint8_t *)key, sec_mode) == true) {
michaeljkoster 0:07581223f90c 395 printf(" Connected. \r\n");
michaeljkoster 0:07581223f90c 396 } else {
michaeljkoster 0:07581223f90c 397 printf(" Connection timed-out (error). Please restart. \r\n");
michaeljkoster 0:07581223f90c 398 while(1);
michaeljkoster 0:07581223f90c 399 }
michaeljkoster 0:07581223f90c 400 }
michaeljkoster 0:07581223f90c 401
michaeljkoster 0:07581223f90c 402 /**
michaeljkoster 0:07581223f90c 403 * \brief Connect to SSID without security
michaeljkoster 0:07581223f90c 404 * \param ssid Name of SSID
michaeljkoster 0:07581223f90c 405 * \return none
michaeljkoster 0:07581223f90c 406 */
michaeljkoster 0:07581223f90c 407 void connect_to_ssid(char *ssid) {
michaeljkoster 0:07581223f90c 408 wifi.connect_open((uint8_t *)ssid);
michaeljkoster 0:07581223f90c 409 }
michaeljkoster 0:07581223f90c 410
michaeljkoster 0:07581223f90c 411 /**
michaeljkoster 0:07581223f90c 412 * \brief First time configuration
michaeljkoster 0:07581223f90c 413 * \param none
michaeljkoster 0:07581223f90c 414 * \return none
michaeljkoster 0:07581223f90c 415 */
michaeljkoster 0:07581223f90c 416 void do_FTC(void) {
michaeljkoster 0:07581223f90c 417 printf("Running First Time Configuration \r\n");
michaeljkoster 0:07581223f90c 418 wifi.start_smart_config(smartconfigkey);
michaeljkoster 0:07581223f90c 419 while (wifi.is_dhcp_configured() == false) {
michaeljkoster 0:07581223f90c 420 wait_ms(500);
michaeljkoster 0:07581223f90c 421 printf("Waiting for dhcp to be set. \r\n");
michaeljkoster 0:07581223f90c 422 }
michaeljkoster 0:07581223f90c 423 user_info.FTC = 1;
michaeljkoster 0:07581223f90c 424 wifi.set_user_file_info((uint8_t *)&user_info, sizeof(user_info));
michaeljkoster 0:07581223f90c 425 wifi._wlan.stop();
michaeljkoster 0:07581223f90c 426 printf("FTC finished. \r\n");
michaeljkoster 0:07581223f90c 427 }
michaeljkoster 0:07581223f90c 428
michaeljkoster 0:07581223f90c 429 /**
michaeljkoster 0:07581223f90c 430 * \brief TCP server demo
michaeljkoster 0:07581223f90c 431 * \param none
michaeljkoster 0:07581223f90c 432 * \return int
michaeljkoster 0:07581223f90c 433 */
michaeljkoster 0:07581223f90c 434 int main() {
michaeljkoster 0:07581223f90c 435 int loop;
michaeljkoster 0:07581223f90c 436 int temp;
michaeljkoster 0:07581223f90c 437 unsigned int oldseconds;
michaeljkoster 0:07581223f90c 438
michaeljkoster 0:07581223f90c 439 //Board dependent init
michaeljkoster 0:07581223f90c 440 init();
michaeljkoster 0:07581223f90c 441
michaeljkoster 0:07581223f90c 442 // Initalize global variables
michaeljkoster 0:07581223f90c 443 axis6.packet_id = 1;
michaeljkoster 0:07581223f90c 444 axis6.timestamp = 0;
michaeljkoster 0:07581223f90c 445 axis6.acc_x = 0;
michaeljkoster 0:07581223f90c 446 axis6.acc_y = 0;
michaeljkoster 0:07581223f90c 447 axis6.acc_z = 0;
michaeljkoster 0:07581223f90c 448 axis6.mag_x = 0;
michaeljkoster 0:07581223f90c 449 axis6.mag_y = 0;
michaeljkoster 0:07581223f90c 450 axis6.mag_z = 0;
michaeljkoster 0:07581223f90c 451 axis6.roll = 0;
michaeljkoster 0:07581223f90c 452 axis6.pitch = 0;
michaeljkoster 0:07581223f90c 453 axis6.yaw = 0;
michaeljkoster 0:07581223f90c 454 axis6.compass = 0;
michaeljkoster 0:07581223f90c 455 axis6.alt = 0;
michaeljkoster 0:07581223f90c 456 axis6.temp = 0;
michaeljkoster 0:07581223f90c 457 axis6.light = 0;
michaeljkoster 0:07581223f90c 458 compass_type = ANDROID_COMPASS;
michaeljkoster 0:07581223f90c 459 seconds = 0;
michaeljkoster 0:07581223f90c 460 server_running = 1;
michaeljkoster 0:07581223f90c 461 newData = 0;
michaeljkoster 0:07581223f90c 462 secondFlag = 0;
michaeljkoster 0:07581223f90c 463 HsecondFlag = 0;
michaeljkoster 0:07581223f90c 464 GREEN_ON;
michaeljkoster 0:07581223f90c 465
michaeljkoster 0:07581223f90c 466 // Unlock I2C bus if blocked by a device
michaeljkoster 0:07581223f90c 467 I2C_busreset();
michaeljkoster 0:07581223f90c 468
sam_grove 16:d6812604cf92 469 // pc.baud(115200);
michaeljkoster 0:07581223f90c 470
michaeljkoster 0:07581223f90c 471 // set current to 500mA since we're turning on the Wi-Fi
michaeljkoster 0:07581223f90c 472 Batt.init(CHRG_500MA);
michaeljkoster 0:07581223f90c 473
michaeljkoster 0:07581223f90c 474 //Init LEDs
michaeljkoster 0:07581223f90c 475 initLEDs();
michaeljkoster 0:07581223f90c 476 // Read the Magnetometer a couple of times to initalize
michaeljkoster 0:07581223f90c 477 for(loop=0 ; loop < 5 ; loop++)
michaeljkoster 0:07581223f90c 478 {
michaeljkoster 0:07581223f90c 479 temp = mag.readReg(0x01);
michaeljkoster 0:07581223f90c 480 temp = mag.readReg(0x02);
michaeljkoster 0:07581223f90c 481 temp = mag.readReg(0x03);
michaeljkoster 0:07581223f90c 482 temp = mag.readReg(0x04);
michaeljkoster 0:07581223f90c 483 temp = mag.readReg(0x05);
michaeljkoster 0:07581223f90c 484 temp = mag.readReg(0x06);
michaeljkoster 0:07581223f90c 485 wait_ms(50);
michaeljkoster 0:07581223f90c 486 }
michaeljkoster 0:07581223f90c 487
michaeljkoster 0:07581223f90c 488 init_eCompass();
michaeljkoster 0:07581223f90c 489
michaeljkoster 0:07581223f90c 490 // Start Ticker
michaeljkoster 0:07581223f90c 491 systick.attach(&SysTick_Handler, 0.01);
michaeljkoster 0:07581223f90c 492 // Trigger a WLAN device
michaeljkoster 0:07581223f90c 493 wifi.init();
michaeljkoster 0:07581223f90c 494 //wifi.start(0);
michaeljkoster 0:07581223f90c 495 printf("CC3000 Wi-Go IOT ARM Sensinode demo.\r\n");
michaeljkoster 0:07581223f90c 496 print_cc3000_info();
michaeljkoster 0:07581223f90c 497 server_running = 1;
michaeljkoster 0:07581223f90c 498 newData = 0;
michaeljkoster 0:07581223f90c 499 GREEN_ON;
michaeljkoster 0:07581223f90c 500
michaeljkoster 0:07581223f90c 501 if(!user_info.FTC)
michaeljkoster 0:07581223f90c 502 {
michaeljkoster 0:07581223f90c 503 do_FTC(); // Call First Time Configuration if SmartConfig has not been run
michaeljkoster 0:07581223f90c 504 printf("Please restart your board. \r\n");
michaeljkoster 0:07581223f90c 505 GreenStop();
michaeljkoster 0:07581223f90c 506 }
michaeljkoster 0:07581223f90c 507
michaeljkoster 0:07581223f90c 508 // Wait for slider touch
michaeljkoster 0:07581223f90c 509 printf("\r\nUse the slider to start an application.\r\n");
michaeljkoster 0:07581223f90c 510 printf("Releasing the slider for more than 3 seconds\r\nwill start the chosen application.\r\n");
michaeljkoster 0:07581223f90c 511 printf("Touching the slider within the 3 seconds\r\ntimeframe allows you to re-select an application.\r\n");
michaeljkoster 0:07581223f90c 512 printf("\r\nThe RGB LED indicates the selection:\r\n");
michaeljkoster 0:07581223f90c 513 printf("ORANGE - Erase all profiles.\r\n");
michaeljkoster 0:07581223f90c 514 printf("PURPLE - Force SmartConfig.\r\n");
michaeljkoster 0:07581223f90c 515 printf("BLUE - Webserver displaying live sensor data.\r\n");
michaeljkoster 0:07581223f90c 516 printf("RED - ARM Sensinode LWM2M client.\r\n");
michaeljkoster 0:07581223f90c 517 printf("GREEN - Android sensor fusion app.\r\n");
michaeljkoster 0:07581223f90c 518 while( tsi.readPercentage() == 0 )
michaeljkoster 0:07581223f90c 519 {
michaeljkoster 0:07581223f90c 520 RED_ON;
michaeljkoster 0:07581223f90c 521 wait(0.2);
michaeljkoster 0:07581223f90c 522 RED_OFF;
michaeljkoster 0:07581223f90c 523 wait(0.2);
michaeljkoster 0:07581223f90c 524 }
michaeljkoster 0:07581223f90c 525 RED_OFF;
michaeljkoster 0:07581223f90c 526
michaeljkoster 0:07581223f90c 527 oldseconds = seconds;
michaeljkoster 0:07581223f90c 528 loop = 100;
michaeljkoster 0:07581223f90c 529 temp = 0;
michaeljkoster 0:07581223f90c 530 // Read slider as long as it is touched.
michaeljkoster 0:07581223f90c 531 // If released for more than 3 seconds, exit
michaeljkoster 0:07581223f90c 532 while((loop != 0) || ((seconds - oldseconds) < 3))
michaeljkoster 0:07581223f90c 533 {
michaeljkoster 0:07581223f90c 534 loop = tsi.readPercentage() * 100;
michaeljkoster 0:07581223f90c 535 if(loop != 0)
michaeljkoster 0:07581223f90c 536 {
michaeljkoster 0:07581223f90c 537 oldseconds = seconds;
michaeljkoster 0:07581223f90c 538 temp = loop;
michaeljkoster 0:07581223f90c 539 }
michaeljkoster 0:07581223f90c 540 if(temp > 80)
michaeljkoster 0:07581223f90c 541 {
michaeljkoster 0:07581223f90c 542 RED_ON; GREEN_ON; BLUE_OFF; //Orange
michaeljkoster 0:07581223f90c 543 }
michaeljkoster 0:07581223f90c 544 else if(temp > 60)
michaeljkoster 0:07581223f90c 545 {
michaeljkoster 0:07581223f90c 546 RED_ON; GREEN_OFF; BLUE_ON; //Purple
michaeljkoster 0:07581223f90c 547 }
michaeljkoster 0:07581223f90c 548 else if(temp > 40)
michaeljkoster 0:07581223f90c 549 {
michaeljkoster 0:07581223f90c 550 RED_OFF; GREEN_OFF; BLUE_ON; //Blue
michaeljkoster 0:07581223f90c 551 }
michaeljkoster 0:07581223f90c 552 else if(temp > 20)
michaeljkoster 0:07581223f90c 553 {
michaeljkoster 0:07581223f90c 554 RED_ON; GREEN_OFF; BLUE_OFF; //Red
michaeljkoster 0:07581223f90c 555 }
michaeljkoster 0:07581223f90c 556 else
michaeljkoster 0:07581223f90c 557 {
michaeljkoster 0:07581223f90c 558 RED_OFF; GREEN_ON; BLUE_OFF; //Green
michaeljkoster 0:07581223f90c 559 }
michaeljkoster 0:07581223f90c 560 }
michaeljkoster 0:07581223f90c 561 RED_OFF; GREEN_OFF; BLUE_OFF;
michaeljkoster 0:07581223f90c 562
michaeljkoster 0:07581223f90c 563 // Execute the user selected application
michaeljkoster 0:07581223f90c 564 if(temp > 80) // Erase all profiles
michaeljkoster 0:07581223f90c 565 {
michaeljkoster 0:07581223f90c 566 server_running = 1;
michaeljkoster 0:07581223f90c 567 RED_OFF; GREEN_OFF; BLUE_OFF;
michaeljkoster 0:07581223f90c 568 printf("\r\nErasing all wireless profiles. \r\n");
michaeljkoster 0:07581223f90c 569 wifi.delete_profiles();
michaeljkoster 0:07581223f90c 570 wifi.stop();
michaeljkoster 0:07581223f90c 571 printf("Finished. Please restart your board. \r\n");
michaeljkoster 0:07581223f90c 572 GreenStop();
michaeljkoster 0:07581223f90c 573 }
michaeljkoster 0:07581223f90c 574
michaeljkoster 0:07581223f90c 575 if(temp > 60) // Force SmartConfig
michaeljkoster 0:07581223f90c 576 {
michaeljkoster 0:07581223f90c 577 server_running = 1;
michaeljkoster 0:07581223f90c 578 RED_OFF; GREEN_OFF; BLUE_OFF;
michaeljkoster 0:07581223f90c 579 printf("\r\nStarting Smart Config configuration. \r\n");
michaeljkoster 0:07581223f90c 580 wifi.start_smart_config(smartconfigkey);
michaeljkoster 0:07581223f90c 581 while (wifi.is_dhcp_configured() == false)
michaeljkoster 0:07581223f90c 582 {
michaeljkoster 0:07581223f90c 583 wait_ms(500);
michaeljkoster 0:07581223f90c 584 printf("Waiting for dhcp to be set. \r\n");
michaeljkoster 0:07581223f90c 585 }
michaeljkoster 0:07581223f90c 586 printf("Finished. Please restart your board. \r\n");
michaeljkoster 0:07581223f90c 587 GreenStop();
michaeljkoster 0:07581223f90c 588 }
michaeljkoster 0:07581223f90c 589
michaeljkoster 0:07581223f90c 590 RED_OFF; GREEN_OFF; BLUE_OFF;
michaeljkoster 0:07581223f90c 591
michaeljkoster 0:07581223f90c 592 printf("\r\nAttempting SSID Connection. \r\n");
michaeljkoster 0:07581223f90c 593 if (wifi.connect() == -1) {
sam_grove 16:d6812604cf92 594 error("Failed to connect. Please verify connection details and try again. \r\n");
michaeljkoster 0:07581223f90c 595 } else {
michaeljkoster 0:07581223f90c 596 printf("Connected - IP address: %s \r\n",wifi.getIPAddress());
michaeljkoster 0:07581223f90c 597 }
michaeljkoster 0:07581223f90c 598 LED_D3_ON;
michaeljkoster 0:07581223f90c 599
michaeljkoster 0:07581223f90c 600 server_running = 0;
michaeljkoster 0:07581223f90c 601
michaeljkoster 0:07581223f90c 602 // Start the selected application
michaeljkoster 0:07581223f90c 603 if(temp > 40) // Run Webserver
michaeljkoster 0:07581223f90c 604 {
michaeljkoster 0:07581223f90c 605 compass_type = NED_COMPASS;
michaeljkoster 0:07581223f90c 606 init_eCompass();
michaeljkoster 0:07581223f90c 607 seconds = 0;
michaeljkoster 0:07581223f90c 608 demo_wifi_main();
michaeljkoster 0:07581223f90c 609 }
michaeljkoster 0:07581223f90c 610 if(temp > 20) // Sensinode LWM2M client
michaeljkoster 0:07581223f90c 611 {
michaeljkoster 0:07581223f90c 612 compass_type = NED_COMPASS;
michaeljkoster 0:07581223f90c 613 init_eCompass();
michaeljkoster 0:07581223f90c 614 seconds = 0;
michaeljkoster 4:727f1aeb717a 615 server_running = 1;
michaeljkoster 0:07581223f90c 616 nsdl_run();
michaeljkoster 0:07581223f90c 617 }
michaeljkoster 4:727f1aeb717a 618 if(temp <= 20)
michaeljkoster 4:727f1aeb717a 619 {
michaeljkoster 4:727f1aeb717a 620 init_eCompass();
michaeljkoster 4:727f1aeb717a 621 seconds = 0;
michaeljkoster 4:727f1aeb717a 622 // Run TCP/IP Connection to host - Sensor Fusion App
michaeljkoster 4:727f1aeb717a 623 runTCPIPserver();
michaeljkoster 4:727f1aeb717a 624 }
michaeljkoster 0:07581223f90c 625 }
michaeljkoster 0:07581223f90c 626