Library set up as dummy module on mbed to mimic Nordic.

Dependencies:   mbed-rtos mbed

Committer:
Stephen_NewVistas
Date:
Mon Dec 12 23:06:58 2016 +0000
Revision:
0:226550611f0d
Child:
1:d6b18299a715
Got system working on bus, calling registered functions with ACK/NACK/RESPONSE. Need to clean up.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Stephen_NewVistas 0:226550611f0d 1 #include <stdio.h>
Stephen_NewVistas 0:226550611f0d 2 #include <string.h>
Stephen_NewVistas 0:226550611f0d 3 #include "packetformatter.h"
Stephen_NewVistas 0:226550611f0d 4 #include "charactercode.h"
Stephen_NewVistas 0:226550611f0d 5 //#include "command.h"
Stephen_NewVistas 0:226550611f0d 6
Stephen_NewVistas 0:226550611f0d 7 //#define DEBUG
Stephen_NewVistas 0:226550611f0d 8
Stephen_NewVistas 0:226550611f0d 9 static unsigned int checkSum;
Stephen_NewVistas 0:226550611f0d 10 static unsigned int packetSize;
Stephen_NewVistas 0:226550611f0d 11 static unsigned char buffer[1024];
Stephen_NewVistas 0:226550611f0d 12
Stephen_NewVistas 0:226550611f0d 13 /******************************************************************************
Stephen_NewVistas 0:226550611f0d 14 * Function ConvertToPacket( Packet *_packet , unsigned char *_buffer )
Stephen_NewVistas 0:226550611f0d 15 *
Stephen_NewVistas 0:226550611f0d 16 * This function is passed an empty packet a buffer with a message. The message
Stephen_NewVistas 0:226550611f0d 17 * is broken down and placed into the packet.
Stephen_NewVistas 0:226550611f0d 18 *
Stephen_NewVistas 0:226550611f0d 19 *
Stephen_NewVistas 0:226550611f0d 20 * PreCondition: None
Stephen_NewVistas 0:226550611f0d 21 *
Stephen_NewVistas 0:226550611f0d 22 * Input: '_packet' - empty packet , '_buffer' - message
Stephen_NewVistas 0:226550611f0d 23 *
Stephen_NewVistas 0:226550611f0d 24 * Output:
Stephen_NewVistas 0:226550611f0d 25 *
Stephen_NewVistas 0:226550611f0d 26 * Side Effects: None
Stephen_NewVistas 0:226550611f0d 27 *
Stephen_NewVistas 0:226550611f0d 28 *****************************************************************************/
Stephen_NewVistas 0:226550611f0d 29 int ConvertToPacket( Packet *_packet , unsigned char *_buffer ){
Stephen_NewVistas 0:226550611f0d 30 memset( _packet , '\0' , sizeof( Packet ) );
Stephen_NewVistas 0:226550611f0d 31
Stephen_NewVistas 0:226550611f0d 32 _packet->deviceID = (int)_buffer[1] ;
Stephen_NewVistas 0:226550611f0d 33 _packet->sourceID = (int)_buffer[2] ;
Stephen_NewVistas 0:226550611f0d 34 _packet->command = _buffer[3];
Stephen_NewVistas 0:226550611f0d 35 _packet->packetLength = _buffer[4];
Stephen_NewVistas 0:226550611f0d 36 _packet->packetLength = _packet->packetLength << 8;
Stephen_NewVistas 0:226550611f0d 37 _packet->packetLength |= _buffer[5];
Stephen_NewVistas 0:226550611f0d 38
Stephen_NewVistas 0:226550611f0d 39 int i;
Stephen_NewVistas 0:226550611f0d 40 for( i = 0 ; i < _packet->packetLength ; i++ ){
Stephen_NewVistas 0:226550611f0d 41 _packet->packetData[i] = *( _buffer + i + 6 );
Stephen_NewVistas 0:226550611f0d 42 }
Stephen_NewVistas 0:226550611f0d 43 return 0;
Stephen_NewVistas 0:226550611f0d 44 }
Stephen_NewVistas 0:226550611f0d 45
Stephen_NewVistas 0:226550611f0d 46 /******************************************************************************
Stephen_NewVistas 0:226550611f0d 47 * Function unsigned short escapedToSpecialChar(unsigned char)
Stephen_NewVistas 0:226550611f0d 48 *
Stephen_NewVistas 0:226550611f0d 49 * This function is called to convert a data if it is a special character (0x7F, 0x8F, 0x8E)
Stephen_NewVistas 0:226550611f0d 50 * to equivalent escaped character.
Stephen_NewVistas 0:226550611f0d 51 *
Stephen_NewVistas 0:226550611f0d 52 * e.g. Special Character Escaped Character
Stephen_NewVistas 0:226550611f0d 53 * 0x7F = 0x8E 0x01
Stephen_NewVistas 0:226550611f0d 54 * 0x8F = 0x8E 0x02
Stephen_NewVistas 0:226550611f0d 55 * 0x8E = 0x8E 0x8E
Stephen_NewVistas 0:226550611f0d 56 *
Stephen_NewVistas 0:226550611f0d 57 * PreCondition: None
Stephen_NewVistas 0:226550611f0d 58 *
Stephen_NewVistas 0:226550611f0d 59 * Input: 'c' - character to convert if it is an special character.
Stephen_NewVistas 0:226550611f0d 60 *
Stephen_NewVistas 0:226550611f0d 61 * Output: Equivalent escaped character
Stephen_NewVistas 0:226550611f0d 62 *
Stephen_NewVistas 0:226550611f0d 63 * Side Effects: None
Stephen_NewVistas 0:226550611f0d 64 *
Stephen_NewVistas 0:226550611f0d 65 *****************************************************************************/
Stephen_NewVistas 0:226550611f0d 66 unsigned short
Stephen_NewVistas 0:226550611f0d 67 specialToEscapedChar(unsigned char c)
Stephen_NewVistas 0:226550611f0d 68 {
Stephen_NewVistas 0:226550611f0d 69
Stephen_NewVistas 0:226550611f0d 70 unsigned short escapedChar = 0;
Stephen_NewVistas 0:226550611f0d 71 char isSpecialChar = ((STARTPOLL == c) || (STARTPACKET == c) || (FLAGBYTE == c));
Stephen_NewVistas 0:226550611f0d 72
Stephen_NewVistas 0:226550611f0d 73 if(isSpecialChar)
Stephen_NewVistas 0:226550611f0d 74 {
Stephen_NewVistas 0:226550611f0d 75 escapedChar = (FLAGBYTE << 8);
Stephen_NewVistas 0:226550611f0d 76 switch(c)
Stephen_NewVistas 0:226550611f0d 77 {
Stephen_NewVistas 0:226550611f0d 78 case STARTPACKET:
Stephen_NewVistas 0:226550611f0d 79 escapedChar |= 0x01;
Stephen_NewVistas 0:226550611f0d 80 break;
Stephen_NewVistas 0:226550611f0d 81 case STARTPOLL:
Stephen_NewVistas 0:226550611f0d 82 escapedChar |= 0x02;
Stephen_NewVistas 0:226550611f0d 83 break;
Stephen_NewVistas 0:226550611f0d 84 case FLAGBYTE:
Stephen_NewVistas 0:226550611f0d 85 escapedChar |= FLAGBYTE;
Stephen_NewVistas 0:226550611f0d 86 break;
Stephen_NewVistas 0:226550611f0d 87 }
Stephen_NewVistas 0:226550611f0d 88 }
Stephen_NewVistas 0:226550611f0d 89 else
Stephen_NewVistas 0:226550611f0d 90 {
Stephen_NewVistas 0:226550611f0d 91 escapedChar = (unsigned char) c;
Stephen_NewVistas 0:226550611f0d 92 }
Stephen_NewVistas 0:226550611f0d 93
Stephen_NewVistas 0:226550611f0d 94 return escapedChar;
Stephen_NewVistas 0:226550611f0d 95 }
Stephen_NewVistas 0:226550611f0d 96
Stephen_NewVistas 0:226550611f0d 97 /******************************************************************************
Stephen_NewVistas 0:226550611f0d 98 * Function static void insertValueToBuffer(unsigned char)
Stephen_NewVistas 0:226550611f0d 99 *
Stephen_NewVistas 0:226550611f0d 100 * This function is called to insert the value to buffer.
Stephen_NewVistas 0:226550611f0d 101 *
Stephen_NewVistas 0:226550611f0d 102 * PreCondition: None
Stephen_NewVistas 0:226550611f0d 103 *
Stephen_NewVistas 0:226550611f0d 104 * Input: 'value' - value to insert in the buffer.
Stephen_NewVistas 0:226550611f0d 105 *
Stephen_NewVistas 0:226550611f0d 106 * Output: None
Stephen_NewVistas 0:226550611f0d 107 *
Stephen_NewVistas 0:226550611f0d 108 * Side Effects: Increment the packetSize variable
Stephen_NewVistas 0:226550611f0d 109 *
Stephen_NewVistas 0:226550611f0d 110 *****************************************************************************/
Stephen_NewVistas 0:226550611f0d 111 static void
Stephen_NewVistas 0:226550611f0d 112 insertValueToBuffer(unsigned char value)
Stephen_NewVistas 0:226550611f0d 113 {
Stephen_NewVistas 0:226550611f0d 114 buffer[packetSize] = value;
Stephen_NewVistas 0:226550611f0d 115 packetSize++;
Stephen_NewVistas 0:226550611f0d 116 }
Stephen_NewVistas 0:226550611f0d 117
Stephen_NewVistas 0:226550611f0d 118 /******************************************************************************
Stephen_NewVistas 0:226550611f0d 119 * Function static void processPacketData(unsigned char)
Stephen_NewVistas 0:226550611f0d 120 *
Stephen_NewVistas 0:226550611f0d 121 * This function is called to process the packet if it is a special character it will
Stephen_NewVistas 0:226550611f0d 122 * convert to escaped character e.g. 0x7F = 0x8E 0x01, 0x8E = 0x8E 0x8E, 0x8F = 0x8E 0x02.
Stephen_NewVistas 0:226550611f0d 123 * The size of return value of specialToEscapedChar function is 2 bytes so it must be inserted
Stephen_NewVistas 0:226550611f0d 124 * in the buffer twice.
Stephen_NewVistas 0:226550611f0d 125 *
Stephen_NewVistas 0:226550611f0d 126 * PreCondition: None
Stephen_NewVistas 0:226550611f0d 127 *
Stephen_NewVistas 0:226550611f0d 128 * Input: 'packetData' - value to convert if it is a special character.
Stephen_NewVistas 0:226550611f0d 129 *
Stephen_NewVistas 0:226550611f0d 130 * Output: None
Stephen_NewVistas 0:226550611f0d 131 *
Stephen_NewVistas 0:226550611f0d 132 * Side Effects: None
Stephen_NewVistas 0:226550611f0d 133 *
Stephen_NewVistas 0:226550611f0d 134 *****************************************************************************/
Stephen_NewVistas 0:226550611f0d 135 static void
Stephen_NewVistas 0:226550611f0d 136 processPacketData(unsigned char packetData)
Stephen_NewVistas 0:226550611f0d 137 {
Stephen_NewVistas 0:226550611f0d 138
Stephen_NewVistas 0:226550611f0d 139 unsigned short packetDataResult = specialToEscapedChar(packetData);
Stephen_NewVistas 0:226550611f0d 140
Stephen_NewVistas 0:226550611f0d 141 if( (packetDataResult >> 8) != 0)
Stephen_NewVistas 0:226550611f0d 142 {
Stephen_NewVistas 0:226550611f0d 143 insertValueToBuffer((unsigned char)(packetDataResult>> 8));
Stephen_NewVistas 0:226550611f0d 144 }
Stephen_NewVistas 0:226550611f0d 145
Stephen_NewVistas 0:226550611f0d 146 insertValueToBuffer((unsigned char) packetDataResult);
Stephen_NewVistas 0:226550611f0d 147
Stephen_NewVistas 0:226550611f0d 148 }
Stephen_NewVistas 0:226550611f0d 149
Stephen_NewVistas 0:226550611f0d 150 /******************************************************************************
Stephen_NewVistas 0:226550611f0d 151 * Function void getFormattedPacket(Packet *, unsigned char *)
Stephen_NewVistas 0:226550611f0d 152 *
Stephen_NewVistas 0:226550611f0d 153 * This function is called to process the packet in to a series of bytes that
Stephen_NewVistas 0:226550611f0d 154 * conforms into the protocol of the communication.
Stephen_NewVistas 0:226550611f0d 155 * Protocol Format Example:
Stephen_NewVistas 0:226550611f0d 156 * 0x7F - Start Packet
Stephen_NewVistas 0:226550611f0d 157 * 0xFE - Device ID
Stephen_NewVistas 0:226550611f0d 158 * 0x01 - Source ID
Stephen_NewVistas 0:226550611f0d 159 * 0x05 - Command type
Stephen_NewVistas 0:226550611f0d 160 * 0x00 - Payload length 1st byte
Stephen_NewVistas 0:226550611f0d 161 * 0x01 - Payload length 2nd byte
Stephen_NewVistas 0:226550611f0d 162 * 0x04 - Payload or data
Stephen_NewVistas 0:226550611f0d 163 * 0x76 - checksum
Stephen_NewVistas 0:226550611f0d 164 *
Stephen_NewVistas 0:226550611f0d 165 *
Stephen_NewVistas 0:226550611f0d 166 * PreCondition: None
Stephen_NewVistas 0:226550611f0d 167 *
Stephen_NewVistas 0:226550611f0d 168 * Input: 'packet' - instance of Packet data structure that contains the
Stephen_NewVistas 0:226550611f0d 169 * following information:
Stephen_NewVistas 0:226550611f0d 170 * + device id
Stephen_NewVistas 0:226550611f0d 171 * + source id
Stephen_NewVistas 0:226550611f0d 172 * + command
Stephen_NewVistas 0:226550611f0d 173 * + packet or payload length
Stephen_NewVistas 0:226550611f0d 174 * + packet or payload
Stephen_NewVistas 0:226550611f0d 175 *
Stephen_NewVistas 0:226550611f0d 176 * 'packetBuffer' - empty buffer that will be the holder of the process data or packet.
Stephen_NewVistas 0:226550611f0d 177 *
Stephen_NewVistas 0:226550611f0d 178 * Output: Total size of data inserted in the buffer.
Stephen_NewVistas 0:226550611f0d 179 *
Stephen_NewVistas 0:226550611f0d 180 * Side Effects: None
Stephen_NewVistas 0:226550611f0d 181 *
Stephen_NewVistas 0:226550611f0d 182 *****************************************************************************/
Stephen_NewVistas 0:226550611f0d 183 int getFormattedPacket(Packet * packet, unsigned char * packetBuffer)
Stephen_NewVistas 0:226550611f0d 184 {
Stephen_NewVistas 0:226550611f0d 185
Stephen_NewVistas 0:226550611f0d 186 checkSum = 0;
Stephen_NewVistas 0:226550611f0d 187 packetSize = 0;
Stephen_NewVistas 0:226550611f0d 188
Stephen_NewVistas 0:226550611f0d 189 insertValueToBuffer(STARTPACKET);
Stephen_NewVistas 0:226550611f0d 190 checkSum += STARTPACKET;
Stephen_NewVistas 0:226550611f0d 191
Stephen_NewVistas 0:226550611f0d 192 #ifdef DEBUG
Stephen_NewVistas 0:226550611f0d 193 printf("Start Packet: %x\n", STARTPACKET);
Stephen_NewVistas 0:226550611f0d 194 #endif
Stephen_NewVistas 0:226550611f0d 195
Stephen_NewVistas 0:226550611f0d 196 processPacketData(packet->deviceID);
Stephen_NewVistas 0:226550611f0d 197 checkSum += packet->deviceID;
Stephen_NewVistas 0:226550611f0d 198
Stephen_NewVistas 0:226550611f0d 199 #ifdef DEBUG
Stephen_NewVistas 0:226550611f0d 200 printf("Device ID: %x\n", packet->deviceID);
Stephen_NewVistas 0:226550611f0d 201 #endif
Stephen_NewVistas 0:226550611f0d 202
Stephen_NewVistas 0:226550611f0d 203 processPacketData(packet->sourceID);
Stephen_NewVistas 0:226550611f0d 204 checkSum += packet->sourceID;
Stephen_NewVistas 0:226550611f0d 205
Stephen_NewVistas 0:226550611f0d 206 #ifdef DEBUG
Stephen_NewVistas 0:226550611f0d 207 printf("Source ID: %x\n", packet->sourceID);
Stephen_NewVistas 0:226550611f0d 208 #endif
Stephen_NewVistas 0:226550611f0d 209
Stephen_NewVistas 0:226550611f0d 210 processPacketData(packet->command);
Stephen_NewVistas 0:226550611f0d 211 checkSum += packet->command;
Stephen_NewVistas 0:226550611f0d 212
Stephen_NewVistas 0:226550611f0d 213 #ifdef DEBUG
Stephen_NewVistas 0:226550611f0d 214 printf("Command: %x\n", packet->command);
Stephen_NewVistas 0:226550611f0d 215 #endif
Stephen_NewVistas 0:226550611f0d 216
Stephen_NewVistas 0:226550611f0d 217 unsigned char mostSignificantBytePacketLength = packet->packetLength >> 8;
Stephen_NewVistas 0:226550611f0d 218 unsigned char leastSignificantBytePacketLength = (unsigned char) packet->packetLength;
Stephen_NewVistas 0:226550611f0d 219 processPacketData(mostSignificantBytePacketLength);
Stephen_NewVistas 0:226550611f0d 220 checkSum += mostSignificantBytePacketLength;
Stephen_NewVistas 0:226550611f0d 221 processPacketData(leastSignificantBytePacketLength);
Stephen_NewVistas 0:226550611f0d 222 checkSum += leastSignificantBytePacketLength;
Stephen_NewVistas 0:226550611f0d 223
Stephen_NewVistas 0:226550611f0d 224 #ifdef DEBUG
Stephen_NewVistas 0:226550611f0d 225 printf("Packet length MSB: %x\n", mostSignificantBytePacketLength);
Stephen_NewVistas 0:226550611f0d 226 printf("Packet length LSB: %x\n", leastSignificantBytePacketLength);
Stephen_NewVistas 0:226550611f0d 227 #endif
Stephen_NewVistas 0:226550611f0d 228
Stephen_NewVistas 0:226550611f0d 229 int i;
Stephen_NewVistas 0:226550611f0d 230 for(i = 0; i < packet->packetLength; i++)
Stephen_NewVistas 0:226550611f0d 231 {
Stephen_NewVistas 0:226550611f0d 232 processPacketData(packet->packetData[i]);
Stephen_NewVistas 0:226550611f0d 233 checkSum += packet->packetData[i];
Stephen_NewVistas 0:226550611f0d 234
Stephen_NewVistas 0:226550611f0d 235 #ifdef DEBUG
Stephen_NewVistas 0:226550611f0d 236 printf("Data %d: %x\n", i, packet->packetData[i]);
Stephen_NewVistas 0:226550611f0d 237 #endif
Stephen_NewVistas 0:226550611f0d 238 }
Stephen_NewVistas 0:226550611f0d 239
Stephen_NewVistas 0:226550611f0d 240 unsigned char checksumLSB = (unsigned char)(checkSum & 0xFF);
Stephen_NewVistas 0:226550611f0d 241 unsigned char twosComplementCheckSum = ~checksumLSB + 1;
Stephen_NewVistas 0:226550611f0d 242 processPacketData(twosComplementCheckSum);
Stephen_NewVistas 0:226550611f0d 243
Stephen_NewVistas 0:226550611f0d 244 #ifdef DEBUG
Stephen_NewVistas 0:226550611f0d 245 printf("Checksum: %x\n", twosComplementCheckSum);
Stephen_NewVistas 0:226550611f0d 246 #endif
Stephen_NewVistas 0:226550611f0d 247
Stephen_NewVistas 0:226550611f0d 248 memcpy(packetBuffer, buffer, packetSize);
Stephen_NewVistas 0:226550611f0d 249
Stephen_NewVistas 0:226550611f0d 250 return packetSize;
Stephen_NewVistas 0:226550611f0d 251 }
Stephen_NewVistas 0:226550611f0d 252
Stephen_NewVistas 0:226550611f0d 253 /******************************************************************************
Stephen_NewVistas 0:226550611f0d 254 * Function void getFormattedBootloaderPacket(unsigned char *, unsigned char *, int)
Stephen_NewVistas 0:226550611f0d 255 *
Stephen_NewVistas 0:226550611f0d 256 * This function is called to process the data in to a series of bytes that
Stephen_NewVistas 0:226550611f0d 257 * conforms into the bootloader protocol.
Stephen_NewVistas 0:226550611f0d 258 * Protocol Format Example:
Stephen_NewVistas 0:226550611f0d 259 * 0x55 - STX or Start of TeXt
Stephen_NewVistas 0:226550611f0d 260 * 0x55 - STX or Start of TeXt
Stephen_NewVistas 0:226550611f0d 261 * 0x01 - Data
Stephen_NewVistas 0:226550611f0d 262 * 0x03 - Data
Stephen_NewVistas 0:226550611f0d 263 * 0x0C - Checksum
Stephen_NewVistas 0:226550611f0d 264 * 0x04 - ETX or End of TeXt
Stephen_NewVistas 0:226550611f0d 265 *
Stephen_NewVistas 0:226550611f0d 266 *
Stephen_NewVistas 0:226550611f0d 267 * PreCondition: None
Stephen_NewVistas 0:226550611f0d 268 *
Stephen_NewVistas 0:226550611f0d 269 * Input:
Stephen_NewVistas 0:226550611f0d 270 * 'buffer' - empty buffer that will be the holder of the process.
Stephen_NewVistas 0:226550611f0d 271 * 'data' - values to be send in bootloader.
Stephen_NewVistas 0:226550611f0d 272 * 'size' - size of data to be send.
Stephen_NewVistas 0:226550611f0d 273 *
Stephen_NewVistas 0:226550611f0d 274 * Output: Total size of data inserted in the buffer.
Stephen_NewVistas 0:226550611f0d 275 *
Stephen_NewVistas 0:226550611f0d 276 * Side Effects: None
Stephen_NewVistas 0:226550611f0d 277 *
Stephen_NewVistas 0:226550611f0d 278 *****************************************************************************/
Stephen_NewVistas 0:226550611f0d 279 int
Stephen_NewVistas 0:226550611f0d 280 getFormattedBootloaderPacket(unsigned char *buffer, unsigned char *data, int size)
Stephen_NewVistas 0:226550611f0d 281 {
Stephen_NewVistas 0:226550611f0d 282 int i;
Stephen_NewVistas 0:226550611f0d 283 int j;
Stephen_NewVistas 0:226550611f0d 284 int sum;
Stephen_NewVistas 0:226550611f0d 285
Stephen_NewVistas 0:226550611f0d 286 i = 0;
Stephen_NewVistas 0:226550611f0d 287 buffer[i++] = STX;
Stephen_NewVistas 0:226550611f0d 288 buffer[i++] = STX;
Stephen_NewVistas 0:226550611f0d 289 sum = 0;
Stephen_NewVistas 0:226550611f0d 290
Stephen_NewVistas 0:226550611f0d 291 for(j = 0; j < size; j++)
Stephen_NewVistas 0:226550611f0d 292 {
Stephen_NewVistas 0:226550611f0d 293 if(data[j] == ETX || data[j] == STX || data[j] == ENQ)
Stephen_NewVistas 0:226550611f0d 294 {
Stephen_NewVistas 0:226550611f0d 295 buffer[j+i++] = ENQ;
Stephen_NewVistas 0:226550611f0d 296 }
Stephen_NewVistas 0:226550611f0d 297
Stephen_NewVistas 0:226550611f0d 298 buffer[j+i] = data[j];
Stephen_NewVistas 0:226550611f0d 299 sum += data[j];
Stephen_NewVistas 0:226550611f0d 300 }
Stephen_NewVistas 0:226550611f0d 301
Stephen_NewVistas 0:226550611f0d 302 sum = ((sum * -1) & 0xFF);
Stephen_NewVistas 0:226550611f0d 303 if (sum == ETX || sum == STX || sum == ENQ)
Stephen_NewVistas 0:226550611f0d 304 buffer[j+i++] = ENQ;
Stephen_NewVistas 0:226550611f0d 305
Stephen_NewVistas 0:226550611f0d 306 buffer[j+i] = sum;
Stephen_NewVistas 0:226550611f0d 307 j++;
Stephen_NewVistas 0:226550611f0d 308 buffer[j+i] = ETX;
Stephen_NewVistas 0:226550611f0d 309 j++;
Stephen_NewVistas 0:226550611f0d 310
Stephen_NewVistas 0:226550611f0d 311 //printf("getFormattedBootloaderPacket return = %d\n",j+i);
Stephen_NewVistas 0:226550611f0d 312
Stephen_NewVistas 0:226550611f0d 313 return (j+i);
Stephen_NewVistas 0:226550611f0d 314 }
Stephen_NewVistas 0:226550611f0d 315
Stephen_NewVistas 0:226550611f0d 316