Add I2CSlave to ov580 master.

Dependencies:   MorseGenerator2

Committer:
claytonk
Date:
Mon Oct 29 00:04:10 2018 +0000
Revision:
7:9c77eaad5102
Parent:
6:85d9ad912c14
Child:
8:10ffd42a3921
still working on getting write to work

Who changed what in which revision?

UserRevisionLine numberNew contents of line
claytonk 7:9c77eaad5102 1 #define TWIS1_ENABLED 1
claytonk 7:9c77eaad5102 2 #define TWIS0_ENABLED 0
claytonk 7:9c77eaad5102 3 #define TWIS_ENABLED 1
claytonk 7:9c77eaad5102 4 #define TWI0_ENABLED 1
claytonk 7:9c77eaad5102 5 #define TWI1_ENABLED 0
claytonk 7:9c77eaad5102 6 #define TWI0_USE_EASY_DMA 1
claytonk 7:9c77eaad5102 7 #define TWI1_USE_EASY_DMA 1
claytonk 7:9c77eaad5102 8 #define TWI_DEFAULT_CONFIG_FREQUENCY 104857600
claytonk 7:9c77eaad5102 9 #define ARDUINO_A4_PIN 14
claytonk 7:9c77eaad5102 10 #define ARDUINO_A5_PIN 15
claytonk 7:9c77eaad5102 11
claytonk 7:9c77eaad5102 12
claytonk 0:605fe136b7ea 13 #include "mbed.h"
claytonk 7:9c77eaad5102 14 //#include <nrfx_config.h> need SDK config instead
claytonk 7:9c77eaad5102 15 //#include "sdk_config.h" not needed now
claytonk 0:605fe136b7ea 16
claytonk 0:605fe136b7ea 17 /*
claytonk 0:605fe136b7ea 18 FEATURE REQUIREMENTS
claytonk 0:605fe136b7ea 19
claytonk 3:6b14862f5f51 20 - I2C write occurs on falling edge of strobe pulse to prevent unknown states
claytonk 3:6b14862f5f51 21
claytonk 3:6b14862f5f51 22 - Stack check occurs on leading edge of strobe pulse to ensure strobes are
claytonk 3:6b14862f5f51 23 set correctly
claytonk 0:605fe136b7ea 24
claytonk 3:6b14862f5f51 25 - Reoccuring enable from app that will prevent the emitters from remaining
claytonk 3:6b14862f5f51 26 on if the app crashes and a turn off command isn't sent
claytonk 0:605fe136b7ea 27 - Can be a counter on the emitter enable > threshold
claytonk 3:6b14862f5f51 28 - Better if it's a counter based on reads from the fault register
claytonk 0:605fe136b7ea 29
claytonk 0:605fe136b7ea 30 -Flood/Dot tagging indicated on GPIO3
claytonk 0:605fe136b7ea 31 - 0 Flood
claytonk 0:605fe136b7ea 32 - 1 DOT
claytonk 0:605fe136b7ea 33
claytonk 0:605fe136b7ea 34 -Fault indication on GPIO4 to indicate to app to reboot
claytonk 0:605fe136b7ea 35 - 0 OK
claytonk 0:605fe136b7ea 36 - 1 Fault/Reboot
claytonk 0:605fe136b7ea 37
claytonk 0:605fe136b7ea 38 I2C write commands
claytonk 0:605fe136b7ea 39 Reg: Information Condition
claytonk 4:fc0c93cb0197 40 0x0000 Emitter enable 0x00 Emitters off
claytonk 0:605fe136b7ea 41 0x01 Dot on
claytonk 0:605fe136b7ea 42 0x10 Flood on
claytonk 0:605fe136b7ea 43 0x11 Flood / Dot on
claytonk 0:605fe136b7ea 44
claytonk 4:fc0c93cb0197 45 0x0001 Dot fault Read from LM36011
claytonk 0:605fe136b7ea 46
claytonk 4:fc0c93cb0197 47 0x0002 Dot Current 0x00 - level_dot_max
claytonk 3:6b14862f5f51 48
claytonk 4:fc0c93cb0197 49 0x0003 Flood Fault Read from LM36011
claytonk 3:6b14862f5f51 50
claytonk 4:fc0c93cb0197 51 0x0004 Flood Current 0x00 - level_flood_max
claytonk 0:605fe136b7ea 52
claytonk 4:fc0c93cb0197 53 0x0005 Fault register bit[0] KILL_VCSEL fault
claytonk 3:6b14862f5f51 54 bit[1] dot fault
claytonk 3:6b14862f5f51 55 bit[2] flood fault
claytonk 3:6b14862f5f51 56 bit[3] unstacked fault
claytonk 3:6b14862f5f51 57 bit[4] ?not in app fault?
claytonk 3:6b14862f5f51 58 bit[5-7] unused
claytonk 3:6b14862f5f51 59
claytonk 3:6b14862f5f51 60
claytonk 4:fc0c93cb0197 61 0x0006 Version number 0x70 = version 7.0
claytonk 0:605fe136b7ea 62
claytonk 0:605fe136b7ea 63 */
claytonk 0:605fe136b7ea 64
claytonk 7:9c77eaad5102 65 #if (TWIS0_ENABLED == 1)
claytonk 7:9c77eaad5102 66 #error TWIS0 is congigured wrong
claytonk 7:9c77eaad5102 67 #endif
claytonk 7:9c77eaad5102 68
claytonk 7:9c77eaad5102 69 #if (TWIS1_ENABLED == 0)
claytonk 7:9c77eaad5102 70 #error TWIS1 is off
claytonk 7:9c77eaad5102 71 #endif
claytonk 6:85d9ad912c14 72
claytonk 7:9c77eaad5102 73 #if (TWIS_ENABLED == 0)
claytonk 7:9c77eaad5102 74 #error TWIS is off
claytonk 7:9c77eaad5102 75 #endif
claytonk 6:85d9ad912c14 76
claytonk 7:9c77eaad5102 77 #if (TWI0_ENABLED == 0)
claytonk 7:9c77eaad5102 78 #error TWI0 is off
claytonk 7:9c77eaad5102 79 #endif
claytonk 7:9c77eaad5102 80
claytonk 7:9c77eaad5102 81 #if (TWI1_ENABLED == 1)
claytonk 7:9c77eaad5102 82 #error TWI1 is congigured wrong
claytonk 7:9c77eaad5102 83 #endif
claytonk 6:85d9ad912c14 84
claytonk 3:6b14862f5f51 85 /* DEFINES */
claytonk 3:6b14862f5f51 86
claytonk 3:6b14862f5f51 87 #define version_number 0x70
claytonk 3:6b14862f5f51 88
claytonk 0:605fe136b7ea 89 // define pins for I2C
claytonk 0:605fe136b7ea 90 #define dot_sda p2
claytonk 0:605fe136b7ea 91 #define dot_scl p4
claytonk 0:605fe136b7ea 92 #define flood_sda p28
claytonk 0:605fe136b7ea 93 #define flood_scl p3
claytonk 0:605fe136b7ea 94 #define ov580_sda p30
claytonk 0:605fe136b7ea 95 #define ov580_scl p31
claytonk 3:6b14862f5f51 96
claytonk 3:6b14862f5f51 97 // define strobe pins
claytonk 6:85d9ad912c14 98 #define strobe_flood p23 // strobe0
claytonk 6:85d9ad912c14 99 #define strobe_dot p24 // strobe1
claytonk 3:6b14862f5f51 100
claytonk 3:6b14862f5f51 101 // define pmw pins
claytonk 0:605fe136b7ea 102 #define pwm_1_pin p29
claytonk 0:605fe136b7ea 103 #define pwm_0_pin p5
claytonk 0:605fe136b7ea 104
claytonk 0:605fe136b7ea 105 // define LED pins
claytonk 0:605fe136b7ea 106 #define ledRed p12
claytonk 0:605fe136b7ea 107 #define ledGreen p17
claytonk 0:605fe136b7ea 108 #define ledBlue p13
claytonk 0:605fe136b7ea 109
claytonk 4:fc0c93cb0197 110 /* THREAD */
claytonk 4:fc0c93cb0197 111 EventQueue queue;
claytonk 4:fc0c93cb0197 112
claytonk 6:85d9ad912c14 113 /* TIMOUT */
claytonk 6:85d9ad912c14 114 //Timeout timeout;
claytonk 6:85d9ad912c14 115
claytonk 4:fc0c93cb0197 116 /* INTERRUPTS */
claytonk 4:fc0c93cb0197 117 //create interupts
claytonk 4:fc0c93cb0197 118 InterruptIn int_strobe_dot(strobe_dot);
claytonk 6:85d9ad912c14 119 InterruptIn int_strobe_flood(strobe_flood); // only need one interrupt in
claytonk 3:6b14862f5f51 120
claytonk 3:6b14862f5f51 121 /* I/O */
claytonk 0:605fe136b7ea 122 // initialize LEDs
claytonk 0:605fe136b7ea 123 DigitalOut red(ledRed,1);
claytonk 0:605fe136b7ea 124 DigitalOut green(ledGreen,1);
claytonk 0:605fe136b7ea 125 DigitalOut blue(ledBlue,1);
claytonk 0:605fe136b7ea 126
claytonk 0:605fe136b7ea 127 // Initialize outputs
claytonk 3:6b14862f5f51 128 DigitalOut pwm_0_output(pwm_0_pin,0); // GPIO 3
claytonk 3:6b14862f5f51 129 DigitalOut pwm_1_output(pwm_1_pin,0); // GPIO 4
claytonk 0:605fe136b7ea 130
claytonk 0:605fe136b7ea 131 // Initialize inputs
claytonk 7:9c77eaad5102 132 DigitalIn strobe0(strobe_flood,PullNone);
claytonk 7:9c77eaad5102 133 DigitalIn strobe1(strobe_dot,PullNone);
claytonk 0:605fe136b7ea 134 DigitalIn vcselFault(p25,PullNone);
claytonk 5:60c20a7f7735 135 DigitalIn killVcsel(p26,PullNone); // vcselFault is 1V8 instead of 3V3
claytonk 0:605fe136b7ea 136
claytonk 7:9c77eaad5102 137 DigitalInOut ovsda(ov580_sda);
claytonk 7:9c77eaad5102 138
claytonk 7:9c77eaad5102 139
claytonk 7:9c77eaad5102 140
claytonk 3:6b14862f5f51 141 /* REGISTERS */
claytonk 0:605fe136b7ea 142 static uint8_t LM36011_addr = 0x64 << 1; //0xC8
claytonk 0:605fe136b7ea 143
claytonk 0:605fe136b7ea 144 // register names
claytonk 0:605fe136b7ea 145 static uint8_t enable_reg = 0x01;
claytonk 0:605fe136b7ea 146 static uint8_t configuration_reg = 0x02;
claytonk 0:605fe136b7ea 147 static uint8_t brightness_reg = 0x03;
claytonk 3:6b14862f5f51 148 //static uint8_t torch_reg = 0x04;
claytonk 3:6b14862f5f51 149 //static uint8_t flags_reg = 0x05;
claytonk 3:6b14862f5f51 150 //static uint8_t device_id_reset_reg = 0x06;
claytonk 0:605fe136b7ea 151
claytonk 0:605fe136b7ea 152 // register settings
claytonk 0:605fe136b7ea 153 static uint8_t enable_ir = 0x05;
claytonk 0:605fe136b7ea 154 static uint8_t disable_ir = 0x20;
claytonk 0:605fe136b7ea 155 static uint8_t enable_flash_timeout = 0x01;
claytonk 0:605fe136b7ea 156
claytonk 0:605fe136b7ea 157 // level settings
claytonk 0:605fe136b7ea 158 static uint8_t level_flood_max = 0x66; // = 1.2 A
claytonk 3:6b14862f5f51 159 static uint8_t level_dot_max = 0x5F; // = 1.03 A
claytonk 0:605fe136b7ea 160 //static uint8_t level_dot_max = 0x3F; // = 0.75 A
claytonk 0:605fe136b7ea 161 //static uint8_t level_dot_max = 0x3C; // = 0.70 A
claytonk 0:605fe136b7ea 162 //static uint8_t level_dot_max = 0x15 //0.257 A
claytonk 3:6b14862f5f51 163 //static uint8_t level_dot_max = 0x1F; // = 352mA
claytonk 0:605fe136b7ea 164
claytonk 3:6b14862f5f51 165 char lm_on[2] = {enable_reg,enable_ir};
claytonk 3:6b14862f5f51 166 char lm_off[2] = {enable_reg,disable_ir};
claytonk 0:605fe136b7ea 167 char lmSafety[2] = {configuration_reg,enable_flash_timeout};
claytonk 0:605fe136b7ea 168
claytonk 0:605fe136b7ea 169 char flashBrightness_dot[2] = {brightness_reg,level_dot_max};
claytonk 0:605fe136b7ea 170 char flashBrightness_flood[2] = {brightness_reg,level_flood_max};
claytonk 0:605fe136b7ea 171
claytonk 3:6b14862f5f51 172 /* I2C */
claytonk 7:9c77eaad5102 173 I2CSlave ov_I2C(ov580_sda,ov580_scl);
claytonk 0:605fe136b7ea 174 I2C flood_I2C(flood_sda,flood_scl);
claytonk 0:605fe136b7ea 175 I2C dot_I2C(dot_sda,dot_scl);
claytonk 6:85d9ad912c14 176
claytonk 0:605fe136b7ea 177
claytonk 3:6b14862f5f51 178 /* VARIABLES */
claytonk 3:6b14862f5f51 179 bool stacked = false;
claytonk 3:6b14862f5f51 180 bool emitter_status_dot = false;
claytonk 7:9c77eaad5102 181 char rcv_buffer[3] = {0,0,0};
claytonk 6:85d9ad912c14 182 bool dot_on = false;
claytonk 6:85d9ad912c14 183 bool flood_on = false;
claytonk 6:85d9ad912c14 184 bool once = false;
claytonk 6:85d9ad912c14 185 //bool in_app = true;
claytonk 6:85d9ad912c14 186 //int stack_counter = 0;
claytonk 3:6b14862f5f51 187
claytonk 3:6b14862f5f51 188 /* FUNCTIONS */
claytonk 1:ffffa383ba7e 189
claytonk 6:85d9ad912c14 190 // WAI
claytonk 6:85d9ad912c14 191 void write_off()
claytonk 6:85d9ad912c14 192 {
claytonk 6:85d9ad912c14 193 dot_I2C.write(LM36011_addr,lm_off,2,false);
claytonk 6:85d9ad912c14 194 flood_I2C.write(LM36011_addr,lm_off,2,false);
claytonk 6:85d9ad912c14 195 }
claytonk 6:85d9ad912c14 196
claytonk 6:85d9ad912c14 197 void write_dot()
claytonk 1:ffffa383ba7e 198 {
claytonk 6:85d9ad912c14 199 flood_I2C.write(LM36011_addr,lm_off,2,false);
claytonk 6:85d9ad912c14 200 dot_I2C.write(LM36011_addr,lm_on,2,false);
claytonk 6:85d9ad912c14 201 }
claytonk 6:85d9ad912c14 202
claytonk 6:85d9ad912c14 203 void write_flood()
claytonk 6:85d9ad912c14 204 {
claytonk 6:85d9ad912c14 205 dot_I2C.write(LM36011_addr,lm_off,2,false);
claytonk 6:85d9ad912c14 206 flood_I2C.write(LM36011_addr,lm_on,2,false);
claytonk 6:85d9ad912c14 207 }
claytonk 6:85d9ad912c14 208
claytonk 6:85d9ad912c14 209 void write_pulsed()
claytonk 6:85d9ad912c14 210 {
claytonk 6:85d9ad912c14 211 if(emitter_status_dot) {
claytonk 6:85d9ad912c14 212 write_dot();
claytonk 6:85d9ad912c14 213 } else {
claytonk 6:85d9ad912c14 214 write_flood();
claytonk 6:85d9ad912c14 215 }
claytonk 1:ffffa383ba7e 216 }
claytonk 1:ffffa383ba7e 217
claytonk 4:fc0c93cb0197 218 void write_once()
claytonk 4:fc0c93cb0197 219 {
claytonk 4:fc0c93cb0197 220 if(stacked) {
claytonk 6:85d9ad912c14 221 write_pulsed();
claytonk 6:85d9ad912c14 222 } else {
claytonk 6:85d9ad912c14 223 if(dot_on) {
claytonk 6:85d9ad912c14 224 write_dot();
claytonk 6:85d9ad912c14 225 } else if(flood_on) {
claytonk 6:85d9ad912c14 226 write_flood();
claytonk 4:fc0c93cb0197 227 } else {
claytonk 6:85d9ad912c14 228 write_off();
claytonk 4:fc0c93cb0197 229 }
claytonk 6:85d9ad912c14 230 }
claytonk 7:9c77eaad5102 231
claytonk 6:85d9ad912c14 232 write_pulsed();
claytonk 6:85d9ad912c14 233 dot_on = false;
claytonk 6:85d9ad912c14 234 flood_on = false;
claytonk 6:85d9ad912c14 235 }
claytonk 6:85d9ad912c14 236
claytonk 6:85d9ad912c14 237 // WAI
claytonk 6:85d9ad912c14 238 void stack_check()
claytonk 6:85d9ad912c14 239 {
claytonk 6:85d9ad912c14 240 stacked = dot_on && flood_on;
claytonk 6:85d9ad912c14 241
claytonk 6:85d9ad912c14 242 if(stacked) {
claytonk 6:85d9ad912c14 243 // toggle dot / flood indicator on PWM 0
claytonk 6:85d9ad912c14 244 emitter_status_dot = !emitter_status_dot;
claytonk 4:fc0c93cb0197 245 } else {
claytonk 6:85d9ad912c14 246 emitter_status_dot = dot_on;
claytonk 4:fc0c93cb0197 247 }
claytonk 4:fc0c93cb0197 248 }
claytonk 4:fc0c93cb0197 249
claytonk 4:fc0c93cb0197 250 void lightsOn()
claytonk 4:fc0c93cb0197 251 {
claytonk 6:85d9ad912c14 252 // toggle once
claytonk 6:85d9ad912c14 253 once = !once;
claytonk 6:85d9ad912c14 254 if(once) {
claytonk 6:85d9ad912c14 255 // check the status of what strobes are firing
claytonk 6:85d9ad912c14 256 stack_check();
claytonk 6:85d9ad912c14 257 // change dot/flood indicator
claytonk 6:85d9ad912c14 258 pwm_0_output = emitter_status_dot;
claytonk 6:85d9ad912c14 259 // indicate VCSEL fault if it exists
claytonk 6:85d9ad912c14 260 pwm_1_output = !vcselFault.read();
claytonk 6:85d9ad912c14 261 // timeout for app exit
claytonk 6:85d9ad912c14 262 //timeout.attach(&write_off,.5);
claytonk 6:85d9ad912c14 263 // write once
claytonk 6:85d9ad912c14 264 queue.call(&write_once);
claytonk 6:85d9ad912c14 265 }
claytonk 4:fc0c93cb0197 266 }
claytonk 4:fc0c93cb0197 267
claytonk 4:fc0c93cb0197 268
claytonk 4:fc0c93cb0197 269
claytonk 4:fc0c93cb0197 270
claytonk 6:85d9ad912c14 271 void dot_check()
claytonk 6:85d9ad912c14 272 {
claytonk 6:85d9ad912c14 273 dot_on = true;
claytonk 6:85d9ad912c14 274
claytonk 6:85d9ad912c14 275 once = false;
claytonk 6:85d9ad912c14 276 //timeout.detach();
claytonk 6:85d9ad912c14 277 }
claytonk 6:85d9ad912c14 278
claytonk 6:85d9ad912c14 279
claytonk 6:85d9ad912c14 280 void flood_check()
claytonk 6:85d9ad912c14 281 {
claytonk 6:85d9ad912c14 282 flood_on = true;
claytonk 6:85d9ad912c14 283
claytonk 6:85d9ad912c14 284 once = false;
claytonk 6:85d9ad912c14 285 //timeout.detach();
claytonk 6:85d9ad912c14 286 }
claytonk 6:85d9ad912c14 287
claytonk 6:85d9ad912c14 288 // TODOS //
claytonk 7:9c77eaad5102 289 // DONE P0 Get illumination working
claytonk 6:85d9ad912c14 290 // P0 Get in app working
claytonk 6:85d9ad912c14 291 // P0 Get watchdog time working
claytonk 6:85d9ad912c14 292 // P1 Bluetooth OTA updates
claytonk 6:85d9ad912c14 293 // P2 Get writing working
claytonk 6:85d9ad912c14 294 // P2 Get reading working
claytonk 6:85d9ad912c14 295 //
claytonk 6:85d9ad912c14 296
claytonk 0:605fe136b7ea 297 // main() runs in its own thread in the OS
claytonk 1:ffffa383ba7e 298 int main()
claytonk 1:ffffa383ba7e 299 {
claytonk 7:9c77eaad5102 300 ovsda.output();
claytonk 7:9c77eaad5102 301 ovsda.mode(OpenDrain);
claytonk 6:85d9ad912c14 302 wait(5);
claytonk 6:85d9ad912c14 303
claytonk 4:fc0c93cb0197 304 Thread eventThread(osPriorityHigh);;
claytonk 4:fc0c93cb0197 305 eventThread.start(callback(&queue, &EventQueue::dispatch_forever));
claytonk 4:fc0c93cb0197 306
claytonk 4:fc0c93cb0197 307 // set interrupts
claytonk 6:85d9ad912c14 308 int_strobe_dot.rise(&dot_check);
claytonk 6:85d9ad912c14 309 int_strobe_flood.rise(&flood_check);
claytonk 4:fc0c93cb0197 310 int_strobe_dot.fall(&lightsOn);
claytonk 6:85d9ad912c14 311 int_strobe_flood.fall(&lightsOn);
claytonk 1:ffffa383ba7e 312
claytonk 0:605fe136b7ea 313 // set I2C Frequency to 400kHz
claytonk 7:9c77eaad5102 314 //flood_I2C.frequency(400000); not needed cause of set defaults
claytonk 7:9c77eaad5102 315 //dot_I2C.frequency(400000); not needed cause of set defaults
claytonk 7:9c77eaad5102 316 ov_I2C.frequency(400000);
claytonk 3:6b14862f5f51 317
claytonk 6:85d9ad912c14 318 //TODO get i2c writes working
claytonk 7:9c77eaad5102 319 ov_I2C.address(0xC0);
claytonk 1:ffffa383ba7e 320
claytonk 0:605fe136b7ea 321 // write safety
claytonk 0:605fe136b7ea 322 flood_I2C.write(LM36011_addr,lmSafety,2,false);
claytonk 0:605fe136b7ea 323 dot_I2C.write(LM36011_addr,lmSafety,2,false);
claytonk 3:6b14862f5f51 324
claytonk 1:ffffa383ba7e 325 // write brightness
claytonk 1:ffffa383ba7e 326 flood_I2C.write(LM36011_addr,flashBrightness_flood,2,false);
claytonk 3:6b14862f5f51 327 dot_I2C.write(LM36011_addr,flashBrightness_dot,2,false);
claytonk 1:ffffa383ba7e 328
claytonk 7:9c77eaad5102 329 char read_buff[2] = {0,0};
claytonk 1:ffffa383ba7e 330
claytonk 0:605fe136b7ea 331 while (true) {
claytonk 4:fc0c93cb0197 332
claytonk 7:9c77eaad5102 333
claytonk 6:85d9ad912c14 334 int i = ov_I2C.receive();
claytonk 1:ffffa383ba7e 335
claytonk 6:85d9ad912c14 336 switch(i) {
claytonk 6:85d9ad912c14 337 case I2CSlave::ReadAddressed:
claytonk 6:85d9ad912c14 338 ov_I2C.write(read_buff[1]);
claytonk 6:85d9ad912c14 339 break;
claytonk 6:85d9ad912c14 340 case I2CSlave::WriteGeneral:
claytonk 6:85d9ad912c14 341 ov_I2C.read(rcv_buffer, 3);
claytonk 6:85d9ad912c14 342 break;
claytonk 6:85d9ad912c14 343 case I2CSlave::WriteAddressed:
claytonk 6:85d9ad912c14 344 ov_I2C.read(rcv_buffer, 3);
claytonk 3:6b14862f5f51 345 green = 0;
claytonk 6:85d9ad912c14 346 //dot_I2C.write(LM36011_addr,lm_on,2,false);
claytonk 6:85d9ad912c14 347 break;
claytonk 6:85d9ad912c14 348 }
claytonk 3:6b14862f5f51 349
claytonk 6:85d9ad912c14 350 // clear buffer
claytonk 6:85d9ad912c14 351 for (int k = 0;
claytonk 6:85d9ad912c14 352 k < 3;
claytonk 6:85d9ad912c14 353 k++) rcv_buffer[i]=0;
claytonk 7:9c77eaad5102 354
claytonk 7:9c77eaad5102 355 //green = !stacked;
claytonk 7:9c77eaad5102 356 //red = stacked;
claytonk 3:6b14862f5f51 357
claytonk 0:605fe136b7ea 358 }
claytonk 0:605fe136b7ea 359 }
claytonk 0:605fe136b7ea 360