Alejandro Ungria Hirte / GA-Test

Dependencies:   mbed-dev

Committer:
aungriah
Date:
Wed Dec 06 21:42:54 2017 +0000
Revision:
0:3333b6066adf
asfaf

Who changed what in which revision?

UserRevisionLine numberNew contents of line
aungriah 0:3333b6066adf 1 #include "mbed.h"
aungriah 0:3333b6066adf 2
aungriah 0:3333b6066adf 3
aungriah 0:3333b6066adf 4 #include "SMConfig.h"
aungriah 0:3333b6066adf 5 #include "DecaWave.h" // DW1000 functions
aungriah 0:3333b6066adf 6 //#include "LMMN2WR.h" // 2-Way-Ranging
aungriah 0:3333b6066adf 7 #include "PC.h" // Serial Port via USB for debugging with Terminal
aungriah 0:3333b6066adf 8 #include "Watchdog.h" // Resets Program if it gets stuck
aungriah 0:3333b6066adf 9 #include "nodes.h"
aungriah 0:3333b6066adf 10
aungriah 0:3333b6066adf 11 // Function Prototypes
aungriah 0:3333b6066adf 12 void dwCallbackTx(const dwt_cb_data_t *rxd);
aungriah 0:3333b6066adf 13 void dwCallbackRx(const dwt_cb_data_t *rxd);
aungriah 0:3333b6066adf 14 int min (int a, int b);
aungriah 0:3333b6066adf 15 void configureDW1000(uint8_t dwMode);
aungriah 0:3333b6066adf 16 void rangeAndDisplayOne(uint8_t addr);
aungriah 0:3333b6066adf 17 void rangeAndDisplayAll();
aungriah 0:3333b6066adf 18 void executeOrder(char* command);
aungriah 0:3333b6066adf 19
aungriah 0:3333b6066adf 20
aungriah 0:3333b6066adf 21 // PA_7 MOSI, PA_6 MISO, PA_5 SCLK, PB_6 CS, PB_9 IRQ
aungriah 0:3333b6066adf 22 SPI decaWaveSpi(PA_7, PA_6, PA_5); // Instance of SPI connection to DW1000
aungriah 0:3333b6066adf 23 DigitalOut decaWaveCs(PB_6);
aungriah 0:3333b6066adf 24 InterruptIn decaWaveIrq(PB_9);
aungriah 0:3333b6066adf 25 DecaWave decaWave = DecaWave(); // Instance of the DW1000
aungriah 0:3333b6066adf 26 BusIn addressInput(PA_10, PB_3, PB_5, PB_4); // Bit 0-3 of Switches to set the adress.
aungriah 0:3333b6066adf 27 PC pc(USBTX, USBRX, 921600); // USB UART Terminal
aungriah 0:3333b6066adf 28 DigitalIn anchorInput(PB_10); // Bit 4 of Switches to set the Anchor.
aungriah 0:3333b6066adf 29 BusIn modeInput(PA_8, PA_9, PC_7); // Bit 5-7 Bits of Switches to set the mode.
aungriah 0:3333b6066adf 30 Watchdog wdt = Watchdog();
aungriah 0:3333b6066adf 31 BeaconNode beaconNode(decaWave);
aungriah 0:3333b6066adf 32 AnchorNode anchorNode(decaWave);
aungriah 0:3333b6066adf 33 BaseStationNode baseStationNode(decaWave);
aungriah 0:3333b6066adf 34 Node *node;
aungriah 0:3333b6066adf 35
aungriah 0:3333b6066adf 36
aungriah 0:3333b6066adf 37 int main() {
aungriah 0:3333b6066adf 38
aungriah 0:3333b6066adf 39 decaWaveSpi.frequency(20000000); // Crank up the SPI frequency from 1Mhz to 3Mhz (maybe more?)
aungriah 0:3333b6066adf 40
aungriah 0:3333b6066adf 41 // Check if Reset was from Watchdog or externally
aungriah 0:3333b6066adf 42 if(RCC->CSR&0x20000000)
aungriah 0:3333b6066adf 43 pc.printf("\r\n\r\n --- !!!!WATCHDOG RESET!!!! --- \r\n\r\n", RCC->CSR);
aungriah 0:3333b6066adf 44 else if(RCC->CSR&0x4000000)
aungriah 0:3333b6066adf 45 pc.printf("\r\n\r\n --- External Reset --- \r\n\r\n", RCC->CSR);
aungriah 0:3333b6066adf 46 __HAL_RCC_CLEAR_RESET_FLAGS();
aungriah 0:3333b6066adf 47
aungriah 0:3333b6066adf 48 // Set all Switches Pull-Down so that it is zero if Switch is not set
aungriah 0:3333b6066adf 49 addressInput.mode(PullDown);
aungriah 0:3333b6066adf 50 anchorInput.mode(PullDown);
aungriah 0:3333b6066adf 51 modeInput.mode(PullDown);
aungriah 0:3333b6066adf 52 wait_ms(50);
aungriah 0:3333b6066adf 53
aungriah 0:3333b6066adf 54 baseStationNode.setAddress(addressInput & addressInput.mask());
aungriah 0:3333b6066adf 55 anchorNode.setAddress(addressInput & addressInput.mask());
aungriah 0:3333b6066adf 56 beaconNode.setAddress(addressInput & addressInput.mask());
aungriah 0:3333b6066adf 57 uint8_t roomadress = modeInput & modeInput.mask());
aungriah 0:3333b6066adf 58 if((addressInput & addressInput.mask()) == BASE_STATION_ADDR){
aungriah 0:3333b6066adf 59 node = &baseStationNode;
aungriah 0:3333b6066adf 60 pc.printf("This node is the Base Station, Adress: %d \r\n \r\n \r\n", node->getAddress());
aungriah 0:3333b6066adf 61 }
aungriah 0:3333b6066adf 62 else if(anchorInput){
aungriah 0:3333b6066adf 63 node = &anchorNode;
aungriah 0:3333b6066adf 64 pc.printf("This node is an Anchor node, Adress: %d \r\n \r\n \r\n", node->getAddress());
aungriah 0:3333b6066adf 65 pc.printf("The room id of the anchor is %d", roomadress);
aungriah 0:3333b6066adf 66 wdt.kick(2); // Set up WatchDog
aungriah 0:3333b6066adf 67 }
aungriah 0:3333b6066adf 68 else{
aungriah 0:3333b6066adf 69 node = &beaconNode;
aungriah 0:3333b6066adf 70 pc.printf("This node is a Beacon, Adress: %d \r\n \r\n \r\n", node->getAddress());
aungriah 0:3333b6066adf 71 wdt.kick(2); // Set up WatchDog
aungriah 0:3333b6066adf 72 }
aungriah 0:3333b6066adf 73
aungriah 0:3333b6066adf 74 //pc.printf(" Adress: %d \r\n \r\n \r\n", node->getAddress());
aungriah 0:3333b6066adf 75
aungriah 0:3333b6066adf 76 configureDW1000(7);
aungriah 0:3333b6066adf 77
aungriah 0:3333b6066adf 78 // TODO turn on RXMode regularly (every couple seconds)
aungriah 0:3333b6066adf 79
aungriah 0:3333b6066adf 80 while(1) {
aungriah 0:3333b6066adf 81
aungriah 0:3333b6066adf 82 // Choose between what to execte based on whether this device is a:
aungriah 0:3333b6066adf 83 // BEACON
aungriah 0:3333b6066adf 84 // BASESTATION
aungriah 0:3333b6066adf 85 // ANCHOR
aungriah 0:3333b6066adf 86 if (!node->isAnchor() && !node->isBaseStation()){
aungriah 0:3333b6066adf 87
aungriah 0:3333b6066adf 88 // THE BEACON EXECUTES THIS
aungriah 0:3333b6066adf 89 if(beaconNode.getRepetitions() > 0){
aungriah 0:3333b6066adf 90 switch(beaconNode.getMode()){
aungriah 0:3333b6066adf 91 case RANGE_ALL: rangeAndDisplayAll();
aungriah 0:3333b6066adf 92 break;
aungriah 0:3333b6066adf 93 case RANGE_ONE: rangeAndDisplayOne(beaconNode.getDestination());
aungriah 0:3333b6066adf 94 break;
aungriah 0:3333b6066adf 95 default: break;
aungriah 0:3333b6066adf 96 }
aungriah 0:3333b6066adf 97 beaconNode.decreaseRepetitions();
aungriah 0:3333b6066adf 98 }
aungriah 0:3333b6066adf 99 else{
aungriah 0:3333b6066adf 100 beaconNode.clearRec();
aungriah 0:3333b6066adf 101 wait_ms(8);
aungriah 0:3333b6066adf 102 }
aungriah 0:3333b6066adf 103 wdt.kick();
aungriah 0:3333b6066adf 104 }
aungriah 0:3333b6066adf 105 else if (node->isBaseStation()){
aungriah 0:3333b6066adf 106
aungriah 0:3333b6066adf 107 pc.printf("Debug Point 1\r\n");
aungriah 0:3333b6066adf 108
aungriah 0:3333b6066adf 109 // EXECUTE THIS IF A BASE STATION
aungriah 0:3333b6066adf 110 pc.readcommand(executeOrder);
aungriah 0:3333b6066adf 111 }
aungriah 0:3333b6066adf 112 else { // All Anchor Action is in the Interrupt functions!
aungriah 0:3333b6066adf 113 // EXECUTE THIS IF AN ANCHOR
aungriah 0:3333b6066adf 114 wait_ms(10);
aungriah 0:3333b6066adf 115 wdt.kick();
aungriah 0:3333b6066adf 116 }
aungriah 0:3333b6066adf 117 }
aungriah 0:3333b6066adf 118 }
aungriah 0:3333b6066adf 119
aungriah 0:3333b6066adf 120
aungriah 0:3333b6066adf 121 void executeOrder(char* command){
aungriah 0:3333b6066adf 122
aungriah 0:3333b6066adf 123 int repetitions = command[3]*100 + command[4]*10 + command[5] - 5328;
aungriah 0:3333b6066adf 124 uint8_t dest1 = command[7] - 48;
aungriah 0:3333b6066adf 125 uint8_t dest2 = command[8] - 48;
aungriah 0:3333b6066adf 126 uint8_t dest3 = command[9] - 48;
aungriah 0:3333b6066adf 127
aungriah 0:3333b6066adf 128 pc.printf("Debug Point 2 to destination 1: %d, repetitions: %d \r\n", dest1, repetitions);
aungriah 0:3333b6066adf 129
aungriah 0:3333b6066adf 130 if (strncmp(command, "all", 3) == 0){
aungriah 0:3333b6066adf 131 baseStationNode.sendOrder(0, NOT_USED, RANGE_ALL, repetitions, Node::BASE_ORDER);
aungriah 0:3333b6066adf 132 // pc.printf("Mode: Range all \r\n");
aungriah 0:3333b6066adf 133 }
aungriah 0:3333b6066adf 134 else if (strncmp(command, "one", 3) == 0){
aungriah 0:3333b6066adf 135
aungriah 0:3333b6066adf 136 pc.printf("Debug Point 3\r\n");
aungriah 0:3333b6066adf 137
aungriah 0:3333b6066adf 138 if(dest1 < 15)
aungriah 0:3333b6066adf 139 {
aungriah 0:3333b6066adf 140 pc.printf("Debug Point 6\r\n");
aungriah 0:3333b6066adf 141 baseStationNode.sendOrder(0, dest1, RANGE_ONE, repetitions, Node::BASE_ORDER);
aungriah 0:3333b6066adf 142 }
aungriah 0:3333b6066adf 143 else
aungriah 0:3333b6066adf 144 {
aungriah 0:3333b6066adf 145 baseStationNode.sendOrder(0, 1, RANGE_ONE, repetitions, Node::BASE_ORDER);
aungriah 0:3333b6066adf 146 }
aungriah 0:3333b6066adf 147 }
aungriah 0:3333b6066adf 148
aungriah 0:3333b6066adf 149 else if (strncmp(command, "bea", 3) == 0){
aungriah 0:3333b6066adf 150 if(dest1 < 15)
aungriah 0:3333b6066adf 151 baseStationNode.sendOrder(dest1, NOT_USED, BECOME_BEACON, NOT_USED, Node::SWITCH_TYPE);
aungriah 0:3333b6066adf 152 else
aungriah 0:3333b6066adf 153 baseStationNode.sendOrder(0, NOT_USED, BECOME_BEACON, NOT_USED, Node::SWITCH_TYPE);
aungriah 0:3333b6066adf 154
aungriah 0:3333b6066adf 155 }
aungriah 0:3333b6066adf 156
aungriah 0:3333b6066adf 157 else if (strncmp(command, "anc", 3) == 0){
aungriah 0:3333b6066adf 158 if(dest1 < 15)
aungriah 0:3333b6066adf 159 baseStationNode.sendOrder(dest1, NOT_USED, BECOME_ANCHOR, NOT_USED, Node::SWITCH_TYPE);
aungriah 0:3333b6066adf 160 else
aungriah 0:3333b6066adf 161 baseStationNode.sendOrder(0, NOT_USED, BECOME_ANCHOR, NOT_USED, Node::SWITCH_TYPE);
aungriah 0:3333b6066adf 162 }
aungriah 0:3333b6066adf 163
aungriah 0:3333b6066adf 164 else if (strncmp(command, "tri", 3) == 0){
aungriah 0:3333b6066adf 165 // Switch them in correct modes (should already be the case)
aungriah 0:3333b6066adf 166 baseStationNode.sendOrder(dest1, NOT_USED, BECOME_BEACON, NOT_USED, Node::SWITCH_TYPE);
aungriah 0:3333b6066adf 167 baseStationNode.sendOrder(dest2, NOT_USED, BECOME_ANCHOR, NOT_USED, Node::SWITCH_TYPE);
aungriah 0:3333b6066adf 168 baseStationNode.sendOrder(dest3, NOT_USED, BECOME_ANCHOR, NOT_USED, Node::SWITCH_TYPE);
aungriah 0:3333b6066adf 169
aungriah 0:3333b6066adf 170 // Ranging from first node
aungriah 0:3333b6066adf 171 baseStationNode.sendOrder(dest1, dest2, RANGE_ONE, repetitions, Node::BASE_ORDER);
aungriah 0:3333b6066adf 172 wait_ms(10*repetitions);
aungriah 0:3333b6066adf 173 baseStationNode.sendOrder(dest1, dest3, RANGE_ONE, repetitions, Node::BASE_ORDER);
aungriah 0:3333b6066adf 174 wait_ms(10*repetitions);
aungriah 0:3333b6066adf 175
aungriah 0:3333b6066adf 176 // Mode Switches
aungriah 0:3333b6066adf 177 baseStationNode.sendOrder(dest2, NOT_USED, BECOME_BEACON, NOT_USED, Node::SWITCH_TYPE);
aungriah 0:3333b6066adf 178 baseStationNode.sendOrder(dest1, NOT_USED, BECOME_ANCHOR, NOT_USED, Node::SWITCH_TYPE);
aungriah 0:3333b6066adf 179
aungriah 0:3333b6066adf 180 // Rangings
aungriah 0:3333b6066adf 181 baseStationNode.sendOrder(dest2, dest1, RANGE_ONE, repetitions, Node::BASE_ORDER);
aungriah 0:3333b6066adf 182 wait_ms(10*repetitions);
aungriah 0:3333b6066adf 183 baseStationNode.sendOrder(dest2, dest3, RANGE_ONE, repetitions, Node::BASE_ORDER);
aungriah 0:3333b6066adf 184 wait_ms(10*repetitions);
aungriah 0:3333b6066adf 185
aungriah 0:3333b6066adf 186 // Mode Switches
aungriah 0:3333b6066adf 187 baseStationNode.sendOrder(dest3, NOT_USED, BECOME_BEACON, NOT_USED, Node::SWITCH_TYPE);
aungriah 0:3333b6066adf 188 baseStationNode.sendOrder(dest2, NOT_USED, BECOME_ANCHOR, NOT_USED, Node::SWITCH_TYPE);
aungriah 0:3333b6066adf 189
aungriah 0:3333b6066adf 190 // Rangings
aungriah 0:3333b6066adf 191 baseStationNode.sendOrder(dest3, dest1, RANGE_ONE, repetitions, Node::BASE_ORDER);
aungriah 0:3333b6066adf 192 wait_ms(10*repetitions);
aungriah 0:3333b6066adf 193 baseStationNode.sendOrder(dest3, dest2, RANGE_ONE, repetitions, Node::BASE_ORDER);
aungriah 0:3333b6066adf 194 wait_ms(10*repetitions);
aungriah 0:3333b6066adf 195
aungriah 0:3333b6066adf 196 // Back to original modes
aungriah 0:3333b6066adf 197 baseStationNode.sendOrder(dest1, NOT_USED, BECOME_BEACON, NOT_USED, Node::SWITCH_TYPE);
aungriah 0:3333b6066adf 198 baseStationNode.sendOrder(dest2, NOT_USED, BECOME_ANCHOR, NOT_USED, Node::SWITCH_TYPE);
aungriah 0:3333b6066adf 199 baseStationNode.sendOrder(dest3, NOT_USED, BECOME_ANCHOR, NOT_USED, Node::SWITCH_TYPE);
aungriah 0:3333b6066adf 200
aungriah 0:3333b6066adf 201 }
aungriah 0:3333b6066adf 202 }
aungriah 0:3333b6066adf 203
aungriah 0:3333b6066adf 204 #pragma Otime // Compiler optimize Runtime at the cost of image size
aungriah 0:3333b6066adf 205 // Called after Frame was received
aungriah 0:3333b6066adf 206 void dwCallbackRx(const dwt_cb_data_t *rxd) {
aungriah 0:3333b6066adf 207 int64_t rxTimeStamp = 0;
aungriah 0:3333b6066adf 208 dwt_readrxdata(node->getRecFrameRef(), min(node->getRecFrameLength(), rxd->datalength), 0); // Read Data Frame from Registers
aungriah 0:3333b6066adf 209
aungriah 0:3333b6066adf 210 dwt_readrxtimestamp((uint8_t*) &rxTimeStamp); // Read Timestamp when the frame was received exactly
aungriah 0:3333b6066adf 211 rxTimeStamp &= MASK_40BIT; //Mask the 40 Bits of the timestamp
aungriah 0:3333b6066adf 212
aungriah 0:3333b6066adf 213 node->callbackRX(rxTimeStamp); // Two Way Ranging Function
aungriah 0:3333b6066adf 214 }
aungriah 0:3333b6066adf 215
aungriah 0:3333b6066adf 216
aungriah 0:3333b6066adf 217 #pragma Otime // Compiler optimize Runtime at the cost of image size
aungriah 0:3333b6066adf 218 // Called after Frame was transmitted
aungriah 0:3333b6066adf 219 void dwCallbackTx(const dwt_cb_data_t *txd) {
aungriah 0:3333b6066adf 220 int64_t txTimeStamp = 0;
aungriah 0:3333b6066adf 221 dwt_readtxtimestamp((uint8_t*) &txTimeStamp); // Read Timestamp when the frame was transmitted exactly
aungriah 0:3333b6066adf 222 txTimeStamp &= MASK_40BIT; // Delete the most significant 8 Bits because the timestamp has only 40 Bits
aungriah 0:3333b6066adf 223
aungriah 0:3333b6066adf 224 node->callbackTX(txTimeStamp); // Two Way Ranging Function
aungriah 0:3333b6066adf 225 }
aungriah 0:3333b6066adf 226
aungriah 0:3333b6066adf 227
aungriah 0:3333b6066adf 228 int min (int a, int b){
aungriah 0:3333b6066adf 229 if(a<=b) return a;
aungriah 0:3333b6066adf 230 return b;
aungriah 0:3333b6066adf 231 }
aungriah 0:3333b6066adf 232
aungriah 0:3333b6066adf 233 void configureDW1000(uint8_t dwMode){
aungriah 0:3333b6066adf 234 dwt_config_t dwConfig;
aungriah 0:3333b6066adf 235 dwt_txconfig_t dwConfigTx;
aungriah 0:3333b6066adf 236
aungriah 0:3333b6066adf 237 SMsetconfig(dwMode, &dwConfig, &dwConfigTx);
aungriah 0:3333b6066adf 238
aungriah 0:3333b6066adf 239 decaWave.setup(dwConfig, dwConfigTx, rfDelays[dwConfig.prf - DWT_PRF_16M], dwCallbackTx, dwCallbackRx);
aungriah 0:3333b6066adf 240
aungriah 0:3333b6066adf 241 pc.printf("%s\r\n", DW1000_DEVICE_DRIVER_VER_STRING);
aungriah 0:3333b6066adf 242 {
aungriah 0:3333b6066adf 243 uint16_t tempvbat = dwt_readtempvbat(1);
aungriah 0:3333b6066adf 244 if (tempvbat>0) {
aungriah 0:3333b6066adf 245 float tempC = 1.13f * (float) (tempvbat >> 8) - 113.0f;
aungriah 0:3333b6066adf 246 float vbatV = 0.0057f * (float) (tempvbat & 0xFF) + 2.3f;
aungriah 0:3333b6066adf 247
aungriah 0:3333b6066adf 248 pc.printf(" Voltage: %f, Temperature: %f\r\n", vbatV, tempC);
aungriah 0:3333b6066adf 249 } else {
aungriah 0:3333b6066adf 250 pc.printf("ERROR: Cannot read voltage/temperature\r\n");
aungriah 0:3333b6066adf 251 }
aungriah 0:3333b6066adf 252 }
aungriah 0:3333b6066adf 253 pc.printf(" Device Lot ID %lu, Part ID %lu\r\n", dwt_getlotid(), dwt_getpartid());
aungriah 0:3333b6066adf 254
aungriah 0:3333b6066adf 255 uint16_t DWID = (dwt_getpartid() & 0xFFFF);
aungriah 0:3333b6066adf 256
aungriah 0:3333b6066adf 257 pc.printf(
aungriah 0:3333b6066adf 258 " Settings %i: \r\n Channel %u (%1.3f GHz w/ %1.3f GHz BW), Datarate %s, \r\n PRF %s, Preamble Code %u, PreambleLength %u symbols, \r\n PAC Size %u, %s SFD, SDF timeout %ul symbols\r\n",
aungriah 0:3333b6066adf 259 dwMode, dwConfig.chan, ChannelFrequency[dwConfig.chan],
aungriah 0:3333b6066adf 260 ChannelBandwidth[dwConfig.chan], ChannelBitrate[dwConfig.dataRate], ChannelPRF[dwConfig.prf],
aungriah 0:3333b6066adf 261 dwConfig.txCode, ChannelPLEN(dwConfig.txPreambLength), ChannelPAC[dwConfig.rxPAC],
aungriah 0:3333b6066adf 262 dwConfig.nsSFD==0?"standard":"non-standard", dwConfig.sfdTO);
aungriah 0:3333b6066adf 263 pc.printf(" Power: NORM %2.1f dB, BOOST: 0.125ms %2.1f dB, 0.25ms %2.1f dB, 0.5ms %2.1f dB\r\n",
aungriah 0:3333b6066adf 264 SMgain(dwConfigTx.power& 0xFF), SMgain((dwConfigTx.power>>24)& 0xFF), SMgain((dwConfigTx.power>>16)& 0xFF),
aungriah 0:3333b6066adf 265 SMgain((dwConfigTx.power>>8)& 0xFF));
aungriah 0:3333b6066adf 266 pc.printf(" Frame length: %d us\r\n", decaWave.computeFrameLength_us());
aungriah 0:3333b6066adf 267 pc.printf(" Antenna Delay set to: %d \r\n", decaWave.getAntennaDelay());
aungriah 0:3333b6066adf 268
aungriah 0:3333b6066adf 269 decaWave.turnonrx(); // start listening
aungriah 0:3333b6066adf 270 }
aungriah 0:3333b6066adf 271
aungriah 0:3333b6066adf 272 void rangeAndDisplayOne(uint8_t addr){
aungriah 0:3333b6066adf 273 beaconNode.requestRanging(addr);
aungriah 0:3333b6066adf 274 pc.printf("%f(%f) \r\n", beaconNode.getDistance(addr), beaconNode.getSignalStrength(addr));
aungriah 0:3333b6066adf 275 }
aungriah 0:3333b6066adf 276
aungriah 0:3333b6066adf 277
aungriah 0:3333b6066adf 278
aungriah 0:3333b6066adf 279 void rangeAndDisplayAll(){
aungriah 0:3333b6066adf 280 beaconNode.requestRangingAll();
aungriah 0:3333b6066adf 281 for(int i = 0; i < ADRESSES_COUNT; i++){
aungriah 0:3333b6066adf 282 /*if(beaconNode.getDistance(i) > -10){
aungriah 0:3333b6066adf 283 pc.printf("#%d %f(%f), ", i, beaconNode.getDistance(i), beaconNode.getSignalStrength(i));
aungriah 0:3333b6066adf 284 }*/
aungriah 0:3333b6066adf 285 }
aungriah 0:3333b6066adf 286 pc.printf("\r\n");
aungriah 0:3333b6066adf 287 }
aungriah 0:3333b6066adf 288