fork of what I have been writing

Dependencies:   Crypto

Committer:
kubitz
Date:
Wed Mar 04 13:49:46 2020 +0000
Revision:
9:4135d0c8dc10
Parent:
8:c30a4106d08c
Child:
10:3669e3d832ed
attempted to add the serial com -debugged but not working

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kubitz 5:de6430aee646 1
kubitz 0:19fd8c1944fb 2 #include "mbed.h"
kubitz 0:19fd8c1944fb 3 #include "SHA256.h"
kubitz 6:5f4a954cb8bc 4 #include "rtos.h"
kubitz 9:4135d0c8dc10 5 #include <stdlib.h>
kubitz 9:4135d0c8dc10 6 #include <string.h>
kubitz 7:aef5b29d7a7c 7
kubitz 9:4135d0c8dc10 8 // Mail variables to pass data to threads
kubitz 9:4135d0c8dc10 9 typedef struct
kubitz 9:4135d0c8dc10 10 {
kubitz 9:4135d0c8dc10 11 uint8_t hash[32]; /* hash of successful nonce */
kubitz 6:5f4a954cb8bc 12 } mail_t;
kubitz 7:aef5b29d7a7c 13 Mail<mail_t, 16> crypto_mail;
kubitz 7:aef5b29d7a7c 14 Mail<uint8_t, 8> inCharQ;
kubitz 9:4135d0c8dc10 15
kubitz 9:4135d0c8dc10 16 // Declaration of threads
kubitz 6:5f4a954cb8bc 17 Thread thread_crypto;
kubitz 9:4135d0c8dc10 18 Thread thread_processor;
kubitz 9:4135d0c8dc10 19 Mutex NewKey_mutex;
kubitz 3:8443825642d1 20
kubitz 9:4135d0c8dc10 21 // Crypto mining variables
kubitz 9:4135d0c8dc10 22 uint8_t sequence[] = {0x45, 0x6D, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64,
kubitz 9:4135d0c8dc10 23 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73,
kubitz 9:4135d0c8dc10 24 0x20, 0x61, 0x72, 0x65, 0x20, 0x66, 0x75, 0x6E,
kubitz 9:4135d0c8dc10 25 0x20, 0x61, 0x6E, 0x64, 0x20, 0x64, 0x6F, 0x20,
kubitz 9:4135d0c8dc10 26 0x61, 0x77, 0x65, 0x73, 0x6F, 0x6D, 0x65, 0x20,
kubitz 9:4135d0c8dc10 27 0x74, 0x68, 0x69, 0x6E, 0x67, 0x73, 0x21, 0x20,
kubitz 9:4135d0c8dc10 28 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
kubitz 9:4135d0c8dc10 29 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
kubitz 9:4135d0c8dc10 30 uint64_t *key = (uint64_t *)&sequence[48];
kubitz 9:4135d0c8dc10 31 uint64_t *nonce = (uint64_t *)&sequence[56];
kubitz 0:19fd8c1944fb 32 uint32_t successful_nonce = 0;
kubitz 0:19fd8c1944fb 33 uint32_t last_nonce_number = 0;
kubitz 9:4135d0c8dc10 34 uint8_t hash[32];
kubitz 9:4135d0c8dc10 35 uint64_t NewKey;
kubitz 5:de6430aee646 36
kubitz 9:4135d0c8dc10 37 // Timing variables for printing calculation rate
kubitz 9:4135d0c8dc10 38 Timer timer_nonce;
kubitz 9:4135d0c8dc10 39 uint32_t previous_time;
kubitz 9:4135d0c8dc10 40
kubitz 9:4135d0c8dc10 41 // Serial port variables
kubitz 8:c30a4106d08c 42 // Max size of serial input is 49 + Null character
kubitz 9:4135d0c8dc10 43 char serial_buffer[50];
kubitz 8:c30a4106d08c 44
kubitz 9:4135d0c8dc10 45 RawSerial pc(USBTX, USBRX);
kubitz 9:4135d0c8dc10 46 char command_category;
kubitz 9:4135d0c8dc10 47 char *trimmed_serial_buffer;
kubitz 9:4135d0c8dc10 48 uint64_t extracted_value_serial_hex;
kubitz 9:4135d0c8dc10 49 uint8_t idx;
kubitz 0:19fd8c1944fb 50 //Photointerrupter input pins
kubitz 0:19fd8c1944fb 51 #define I1pin D3
kubitz 0:19fd8c1944fb 52 #define I2pin D6
kubitz 0:19fd8c1944fb 53 #define I3pin D5
kubitz 0:19fd8c1944fb 54
kubitz 0:19fd8c1944fb 55 //Incremental encoder input pins
kubitz 9:4135d0c8dc10 56 #define CHApin D12
kubitz 9:4135d0c8dc10 57 #define CHBpin D11
kubitz 0:19fd8c1944fb 58
kubitz 0:19fd8c1944fb 59 //Motor Drive output pins //Mask in output byte
kubitz 9:4135d0c8dc10 60 #define L1Lpin D1 //0x01
kubitz 9:4135d0c8dc10 61 #define L1Hpin A3 //0x02
kubitz 9:4135d0c8dc10 62 #define L2Lpin D0 //0x04
kubitz 9:4135d0c8dc10 63 #define L2Hpin A6 //0x08
kubitz 9:4135d0c8dc10 64 #define L3Lpin D10 //0x10
kubitz 9:4135d0c8dc10 65 #define L3Hpin D2 //0x20
kubitz 0:19fd8c1944fb 66
kubitz 0:19fd8c1944fb 67 #define PWMpin D9
kubitz 0:19fd8c1944fb 68
kubitz 0:19fd8c1944fb 69 //Motor current sense
kubitz 9:4135d0c8dc10 70 #define MCSPpin A1
kubitz 9:4135d0c8dc10 71 #define MCSNpin A0
kubitz 0:19fd8c1944fb 72
kubitz 0:19fd8c1944fb 73 //Test outputs
kubitz 0:19fd8c1944fb 74 #define TP0pin D4
kubitz 0:19fd8c1944fb 75 #define TP1pin D13
kubitz 0:19fd8c1944fb 76 #define TP2pin A2
kubitz 0:19fd8c1944fb 77
kubitz 0:19fd8c1944fb 78 //Mapping from sequential drive states to motor phase outputs
kubitz 0:19fd8c1944fb 79 /*
kubitz 0:19fd8c1944fb 80 State L1 L2 L3
kubitz 0:19fd8c1944fb 81 0 H - L
kubitz 0:19fd8c1944fb 82 1 - H L
kubitz 0:19fd8c1944fb 83 2 L H -
kubitz 0:19fd8c1944fb 84 3 L - H
kubitz 0:19fd8c1944fb 85 4 - L H
kubitz 0:19fd8c1944fb 86 5 H L -
kubitz 0:19fd8c1944fb 87 6 - - -
kubitz 0:19fd8c1944fb 88 7 - - -
kubitz 0:19fd8c1944fb 89 */
kubitz 0:19fd8c1944fb 90 //Drive state to output table
kubitz 9:4135d0c8dc10 91 const int8_t driveTable[] = {0x12, 0x18, 0x09, 0x21, 0x24, 0x06, 0x00, 0x00};
kubitz 0:19fd8c1944fb 92
kubitz 0:19fd8c1944fb 93 //Mapping from interrupter inputs to sequential rotor states. 0x00 and 0x07 are not valid
kubitz 9:4135d0c8dc10 94 const int8_t stateMap[] = {0x07, 0x05, 0x03, 0x04, 0x01, 0x00, 0x02, 0x07};
kubitz 0:19fd8c1944fb 95 //const int8_t stateMap[] = {0x07,0x01,0x03,0x02,0x05,0x00,0x04,0x07}; //Alternative if phase order of input or drive is reversed
kubitz 0:19fd8c1944fb 96
kubitz 0:19fd8c1944fb 97 //Phase lead to make motor spin
kubitz 9:4135d0c8dc10 98 const int8_t lead = 2; //2 for forwards, -2 for backwards
kubitz 0:19fd8c1944fb 99
kubitz 0:19fd8c1944fb 100 //Status LED
kubitz 0:19fd8c1944fb 101 DigitalOut led1(LED1);
kubitz 0:19fd8c1944fb 102
kubitz 0:19fd8c1944fb 103 //Photointerrupter inputs
kubitz 0:19fd8c1944fb 104 InterruptIn I1(I1pin);
kubitz 0:19fd8c1944fb 105 InterruptIn I2(I2pin);
kubitz 0:19fd8c1944fb 106 InterruptIn I3(I3pin);
kubitz 0:19fd8c1944fb 107
kubitz 0:19fd8c1944fb 108 //Motor Drive outputs
kubitz 0:19fd8c1944fb 109 DigitalOut L1L(L1Lpin);
kubitz 0:19fd8c1944fb 110 DigitalOut L1H(L1Hpin);
kubitz 0:19fd8c1944fb 111 DigitalOut L2L(L2Lpin);
kubitz 0:19fd8c1944fb 112 DigitalOut L2H(L2Hpin);
kubitz 0:19fd8c1944fb 113 DigitalOut L3L(L3Lpin);
kubitz 0:19fd8c1944fb 114 DigitalOut L3H(L3Hpin);
kubitz 0:19fd8c1944fb 115
kubitz 0:19fd8c1944fb 116 DigitalOut TP1(TP1pin);
kubitz 0:19fd8c1944fb 117 PwmOut MotorPWM(PWMpin);
kubitz 0:19fd8c1944fb 118
kubitz 9:4135d0c8dc10 119 int8_t orState = 0; //Rotot offset at motor state 0
kubitz 0:19fd8c1944fb 120 int8_t intState = 0;
kubitz 0:19fd8c1944fb 121 int8_t intStateOld = 0;
kubitz 0:19fd8c1944fb 122
kubitz 0:19fd8c1944fb 123 //Set a given drive state
kubitz 9:4135d0c8dc10 124 void motorOut(int8_t driveState)
kubitz 9:4135d0c8dc10 125 {
kubitz 9:4135d0c8dc10 126
kubitz 0:19fd8c1944fb 127 //Lookup the output byte from the drive state.
kubitz 0:19fd8c1944fb 128 int8_t driveOut = driveTable[driveState & 0x07];
kubitz 9:4135d0c8dc10 129
kubitz 0:19fd8c1944fb 130 //Turn off first
kubitz 9:4135d0c8dc10 131 if (~driveOut & 0x01)
kubitz 9:4135d0c8dc10 132 L1L = 0;
kubitz 9:4135d0c8dc10 133 if (~driveOut & 0x02)
kubitz 9:4135d0c8dc10 134 L1H = 1;
kubitz 9:4135d0c8dc10 135 if (~driveOut & 0x04)
kubitz 9:4135d0c8dc10 136 L2L = 0;
kubitz 9:4135d0c8dc10 137 if (~driveOut & 0x08)
kubitz 9:4135d0c8dc10 138 L2H = 1;
kubitz 9:4135d0c8dc10 139 if (~driveOut & 0x10)
kubitz 9:4135d0c8dc10 140 L3L = 0;
kubitz 9:4135d0c8dc10 141 if (~driveOut & 0x20)
kubitz 9:4135d0c8dc10 142 L3H = 1;
kubitz 9:4135d0c8dc10 143
kubitz 0:19fd8c1944fb 144 //Then turn on
kubitz 9:4135d0c8dc10 145 if (driveOut & 0x01)
kubitz 9:4135d0c8dc10 146 L1L = 1;
kubitz 9:4135d0c8dc10 147 if (driveOut & 0x02)
kubitz 9:4135d0c8dc10 148 L1H = 0;
kubitz 9:4135d0c8dc10 149 if (driveOut & 0x04)
kubitz 9:4135d0c8dc10 150 L2L = 1;
kubitz 9:4135d0c8dc10 151 if (driveOut & 0x08)
kubitz 9:4135d0c8dc10 152 L2H = 0;
kubitz 9:4135d0c8dc10 153 if (driveOut & 0x10)
kubitz 9:4135d0c8dc10 154 L3L = 1;
kubitz 9:4135d0c8dc10 155 if (driveOut & 0x20)
kubitz 9:4135d0c8dc10 156 L3H = 0;
kubitz 9:4135d0c8dc10 157 }
kubitz 0:19fd8c1944fb 158
kubitz 9:4135d0c8dc10 159 //Convert photointerrupter inputs to a rotor state
kubitz 9:4135d0c8dc10 160 inline int8_t readRotorState()
kubitz 9:4135d0c8dc10 161 {
kubitz 9:4135d0c8dc10 162 return stateMap[I1 + 2 * I2 + 4 * I3];
kubitz 9:4135d0c8dc10 163 }
kubitz 9:4135d0c8dc10 164
kubitz 9:4135d0c8dc10 165 //Basic synchronisation routine
kubitz 9:4135d0c8dc10 166 int8_t motorHome()
kubitz 9:4135d0c8dc10 167 {
kubitz 0:19fd8c1944fb 168 //Put the motor in drive state 0 and wait for it to stabilise
kubitz 0:19fd8c1944fb 169 motorOut(0);
kubitz 0:19fd8c1944fb 170 wait(2.0);
kubitz 9:4135d0c8dc10 171
kubitz 0:19fd8c1944fb 172 //Get the rotor state
kubitz 0:19fd8c1944fb 173 return readRotorState();
kubitz 0:19fd8c1944fb 174 }
kubitz 0:19fd8c1944fb 175
kubitz 9:4135d0c8dc10 176 void move()
kubitz 9:4135d0c8dc10 177 {
kubitz 0:19fd8c1944fb 178 intState = readRotorState();
kubitz 9:4135d0c8dc10 179 motorOut((intState - orState + lead + 6) % 6); //+6 to make sure the remainder is positive
kubitz 0:19fd8c1944fb 180 intStateOld = intState;
kubitz 0:19fd8c1944fb 181 }
kubitz 0:19fd8c1944fb 182
kubitz 6:5f4a954cb8bc 183 // Thread to print successful Hashes
kubitz 9:4135d0c8dc10 184 void thread_crypto_print()
kubitz 9:4135d0c8dc10 185 {
kubitz 9:4135d0c8dc10 186 while (true)
kubitz 9:4135d0c8dc10 187 {
kubitz 7:aef5b29d7a7c 188 osEvent evt = crypto_mail.get();
kubitz 9:4135d0c8dc10 189 if (evt.status == osEventMail)
kubitz 9:4135d0c8dc10 190 {
kubitz 9:4135d0c8dc10 191 mail_t *mail = (mail_t *)evt.value.p;
kubitz 6:5f4a954cb8bc 192 for (int i = 0; i < 32; i++)
kubitz 7:aef5b29d7a7c 193 printf("%02x", mail->hash[i]);
kubitz 9:4135d0c8dc10 194 printf("\n\r");
kubitz 7:aef5b29d7a7c 195 crypto_mail.free(mail);
kubitz 6:5f4a954cb8bc 196 }
kubitz 6:5f4a954cb8bc 197 }
kubitz 6:5f4a954cb8bc 198 }
kubitz 6:5f4a954cb8bc 199
kubitz 9:4135d0c8dc10 200 void decode_serial_buffer(char*serial_buffer)
kubitz 9:4135d0c8dc10 201 {
kubitz 9:4135d0c8dc10 202 command_category = serial_buffer[0];
kubitz 9:4135d0c8dc10 203 trimmed_serial_buffer = serial_buffer + 1;
kubitz 9:4135d0c8dc10 204 switch (command_category)
kubitz 9:4135d0c8dc10 205 {
kubitz 9:4135d0c8dc10 206 case 'R':
kubitz 9:4135d0c8dc10 207 // Rotation command - R-?\d{1,s4}(\.\d)?
kubitz 9:4135d0c8dc10 208 pc.printf("You have entered a rotational command\n");
kubitz 9:4135d0c8dc10 209
kubitz 9:4135d0c8dc10 210 // to implement !
kubitz 9:4135d0c8dc10 211
kubitz 9:4135d0c8dc10 212 break;
kubitz 9:4135d0c8dc10 213 case 'V':
kubitz 9:4135d0c8dc10 214 // Speed command - V\d{1,3}(\.\d)?
kubitz 9:4135d0c8dc10 215 pc.printf("You have entered a speed command\n");
kubitz 9:4135d0c8dc10 216 // to implement !
kubitz 9:4135d0c8dc10 217 break;
kubitz 9:4135d0c8dc10 218
kubitz 9:4135d0c8dc10 219 case 'K':
kubitz 9:4135d0c8dc10 220 // Bitcoin key command - K[0-9a-fA-F]{16}
kubitz 9:4135d0c8dc10 221 NewKey_mutex.lock();
kubitz 9:4135d0c8dc10 222 NewKey = (uint64_t)strtoll(trimmed_serial_buffer, NULL, 16);
kubitz 9:4135d0c8dc10 223 pc.printf("\nYou have entered a new bitcoin key: %llu\n", extracted_value_serial_hex);
kubitz 9:4135d0c8dc10 224 NewKey_mutex.unlock();
kubitz 9:4135d0c8dc10 225 break;
kubitz 9:4135d0c8dc10 226
kubitz 9:4135d0c8dc10 227 case 'T':
kubitz 9:4135d0c8dc10 228 // Melody command - T([A-G][#^]?[1-8]){1,16}
kubitz 9:4135d0c8dc10 229 pc.printf("You have entered a melody\n");
kubitz 9:4135d0c8dc10 230
kubitz 9:4135d0c8dc10 231 // to implement !
kubitz 8:c30a4106d08c 232
kubitz 9:4135d0c8dc10 233 default:
kubitz 9:4135d0c8dc10 234 printf("Input value out of format - please try again\n");
kubitz 7:aef5b29d7a7c 235 }
kubitz 9:4135d0c8dc10 236 }
kubitz 9:4135d0c8dc10 237
kubitz 9:4135d0c8dc10 238 // Thread processor raw serial inputs:
kubitz 9:4135d0c8dc10 239 void thread_processor_callback()
kubitz 9:4135d0c8dc10 240 {
kubitz 9:4135d0c8dc10 241 idx = 0;
kubitz 9:4135d0c8dc10 242 memset(serial_buffer, 0, 50);
kubitz 7:aef5b29d7a7c 243
kubitz 9:4135d0c8dc10 244 while (true)
kubitz 9:4135d0c8dc10 245 {
kubitz 9:4135d0c8dc10 246 osEvent evt = inCharQ.get();
kubitz 9:4135d0c8dc10 247
kubitz 9:4135d0c8dc10 248 uint8_t *newChar = (uint8_t *)evt.value.p;
kubitz 9:4135d0c8dc10 249 //Store the new character
kubitz 9:4135d0c8dc10 250 serial_buffer[idx] = *newChar;
kubitz 9:4135d0c8dc10 251 idx = idx + 1;
kubitz 9:4135d0c8dc10 252 pc.printf("inside thread index: %d", idx);
kubitz 9:4135d0c8dc10 253 if (serial_buffer[idx-1] = '\r')
kubitz 9:4135d0c8dc10 254 {
kubitz 9:4135d0c8dc10 255 serial_buffer[idx] = '\0';
kubitz 9:4135d0c8dc10 256 decode_serial_buffer(serial_buffer);
kubitz 9:4135d0c8dc10 257 idx = 0;
kubitz 9:4135d0c8dc10 258 memset(serial_buffer, 0, 50);
kubitz 9:4135d0c8dc10 259 }
kubitz 9:4135d0c8dc10 260 inCharQ.free(newChar);
kubitz 9:4135d0c8dc10 261
kubitz 9:4135d0c8dc10 262 }
kubitz 9:4135d0c8dc10 263 }
kubitz 9:4135d0c8dc10 264
kubitz 9:4135d0c8dc10 265
kubitz 9:4135d0c8dc10 266 // Put message in Mail box for Crypto printing
kubitz 9:4135d0c8dc10 267 void putMessageCrypto(uint8_t *hash)
kubitz 9:4135d0c8dc10 268 {
kubitz 7:aef5b29d7a7c 269 mail_t *mail = crypto_mail.alloc();
kubitz 9:4135d0c8dc10 270
kubitz 9:4135d0c8dc10 271 for (int loop = 0; loop < 32; loop++)
kubitz 9:4135d0c8dc10 272 {
kubitz 9:4135d0c8dc10 273 mail->hash[loop] = hash[loop];
kubitz 7:aef5b29d7a7c 274 }
kubitz 7:aef5b29d7a7c 275 crypto_mail.put(mail);
kubitz 9:4135d0c8dc10 276 }
kubitz 9:4135d0c8dc10 277
kubitz 7:aef5b29d7a7c 278 // ISR routine to get charachter from Serial command
kubitz 9:4135d0c8dc10 279 void serialISR()
kubitz 9:4135d0c8dc10 280 {
kubitz 9:4135d0c8dc10 281 uint8_t *newChar = inCharQ.alloc();
kubitz 9:4135d0c8dc10 282 *newChar = pc.getc();
kubitz 9:4135d0c8dc10 283 inCharQ.put(newChar);
kubitz 9:4135d0c8dc10 284 }
kubitz 9:4135d0c8dc10 285
kubitz 9:4135d0c8dc10 286 // Attach interrupt routine on serial port
kubitz 6:5f4a954cb8bc 287
kubitz 0:19fd8c1944fb 288 //Main
kubitz 9:4135d0c8dc10 289 int main()
kubitz 9:4135d0c8dc10 290 {
kubitz 9:4135d0c8dc10 291 pc.attach(&serialISR);
kubitz 0:19fd8c1944fb 292 const int32_t PWM_PRD = 2500;
kubitz 0:19fd8c1944fb 293 MotorPWM.period_us(PWM_PRD);
kubitz 0:19fd8c1944fb 294 MotorPWM.pulsewidth_us(PWM_PRD);
kubitz 9:4135d0c8dc10 295
kubitz 0:19fd8c1944fb 296 pc.printf("Hello\n\r");
kubitz 9:4135d0c8dc10 297
kubitz 0:19fd8c1944fb 298 //Run the motor synchronisation
kubitz 0:19fd8c1944fb 299 orState = motorHome();
kubitz 9:4135d0c8dc10 300 pc.printf("Rotor origin: %x\n\r", orState);
kubitz 9:4135d0c8dc10 301
kubitz 0:19fd8c1944fb 302 I1.rise(&move);
kubitz 0:19fd8c1944fb 303 I1.fall(&move);
kubitz 0:19fd8c1944fb 304 I2.rise(&move);
kubitz 0:19fd8c1944fb 305 I2.fall(&move);
kubitz 0:19fd8c1944fb 306 I3.rise(&move);
kubitz 0:19fd8c1944fb 307 I3.fall(&move);
kubitz 8:c30a4106d08c 308
kubitz 9:4135d0c8dc10 309 // Initialize threads and timers
kubitz 9:4135d0c8dc10 310 timer_nonce.start();
kubitz 7:aef5b29d7a7c 311 thread_crypto.start(thread_crypto_print);
kubitz 9:4135d0c8dc10 312 thread_processor.start(thread_processor_callback);
kubitz 9:4135d0c8dc10 313 uint8_t hash[32];
kubitz 5:de6430aee646 314
kubitz 9:4135d0c8dc10 315 while (1)
kubitz 9:4135d0c8dc10 316 {
kubitz 9:4135d0c8dc10 317 SHA256::computeHash(hash, (uint8_t *)sequence, 64);
kubitz 5:de6430aee646 318 *nonce = *nonce + 1;
kubitz 5:de6430aee646 319
kubitz 9:4135d0c8dc10 320 if ((hash[0] == 0) && (hash[1] == 0))
kubitz 9:4135d0c8dc10 321 {
kubitz 0:19fd8c1944fb 322 last_nonce_number = successful_nonce;
kubitz 9:4135d0c8dc10 323 putMessageCrypto(hash);
kubitz 0:19fd8c1944fb 324 successful_nonce++;
kubitz 9:4135d0c8dc10 325 }
kubitz 9:4135d0c8dc10 326
kubitz 9:4135d0c8dc10 327 if ((timer_nonce.read_ms() - previous_time) > 1000)
kubitz 9:4135d0c8dc10 328 {
kubitz 9:4135d0c8dc10 329 //pc.printf("Computation Rate: %lu computation /sec\n\r", (*nonce - last_nonce_number));
kubitz 0:19fd8c1944fb 330 last_nonce_number = *nonce;
kubitz 5:de6430aee646 331 previous_time = timer_nonce.read_ms();
kubitz 0:19fd8c1944fb 332 }
kubitz 0:19fd8c1944fb 333 }
kubitz 0:19fd8c1944fb 334
kubitz 9:4135d0c8dc10 335 return 0;
kubitz 9:4135d0c8dc10 336 }