00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include <sys/lnp.h>
00044
00045 #ifdef CONF_LNP
00046
00047 #include <sys/lnp-logical.h>
00048 #include <sys/irq.h>
00049 #include <stdlib.h>
00050
00051 #ifdef CONF_VIS
00052 #include <dlcd.h>
00053 #include <sys/lcd.h>
00054 #endif
00055
00056 #ifdef CONF_AUTOSHUTOFF
00057 #include <sys/timeout.h>
00058 #endif
00059
00060 #include <string.h>
00061
00063
00064
00065
00067
00070 unsigned char lnp_hostaddr = (CONF_LNP_HOSTADDR << 4) & CONF_LNP_HOSTMASK;
00071
00073 volatile unsigned short lnp_timeout_counter;
00074
00076 unsigned short lnp_timeout=LNP_BYTE_TIMEOUT;
00077
00079 lnp_integrity_state_t lnp_integrity_state;
00080
00082
00084 volatile lnp_integrity_handler_t lnp_integrity_handler;
00085
00087
00090 volatile lnp_addressing_handler_t lnp_addressing_handler[LNP_PORTMASK+1];
00091
00092 #if !defined(CONF_MM)
00093 static char lnp_buffer[260];
00094 #endif // CONF_MM
00095
00096 #if defined(CONF_RCX_PROTOCOL)
00097
00098 lnp_remote_handler_t lnp_remote_handler;
00099
00101 const unsigned char lnp_rcx_header[LNP_RCX_HEADER_LENGTH] = {0xff,0x00};
00102
00104 const unsigned char lnp_rcx_remote_op[LNP_RCX_REMOTE_OP_LENGTH] = {0xd2,0x2d};
00105
00106
00108 unsigned char lnp_rcx_temp0;
00109 unsigned char lnp_rcx_temp1;
00110
00112 unsigned char lnp_rcx_checksum;
00113
00114 #endif
00115
00116 #if defined(CONF_RCX_MESSAGE)
00117
00118 const unsigned char lnp_rcx_msg_op[LNP_RCX_MSG_OP_LENGTH] = {0xf7,0x08};
00119
00121 unsigned char lnp_rcx_message;
00122
00123 #endif
00124
00126
00127
00128
00130
00131 #define lnp_checksum_init(sum) (unsigned char)((sum) = 0xff)
00132 #define lnp_checksum_step(sum,d) (unsigned char)((sum) += (d))
00133
00134 #ifdef CONF_HOST
00135 unsigned char lnp_checksum_copy( unsigned char *dest,
00136 const unsigned char *data,
00137 unsigned length )
00138 {
00139 unsigned char a = 0xff;
00140 unsigned char t;
00141
00142 do {
00143 t = *data++;
00144 a += t;
00145 *dest++ = t;
00146 length--;
00147 } while (length > 0);
00148
00149 return a;
00150 }
00151 #else
00152 __asm__(
00153 ".text\n"
00154 "_lnp_checksum_copy:\n"
00155 ";; r0: dest, r1: data, r2: length;\n"
00156
00157 " add.w r0,r2 ; r2: end \n"
00158 " mov.b #0xff,r3l ; r3l: a \n"
00159
00160 "0:\n"
00161 " mov.b @r1+,r3h ; r3h = *data++ \n"
00162 " add.b r3h,r3l ; a += r3h \n"
00163 " mov.b r3h,@r0 ; *dest++ = r3h \n"
00164 " adds #1,r0 \n"
00165 " cmp.w r0,r2 \n"
00166 " bne 0b \n"
00167
00168 " sub.w r0,r0 \n"
00169 " mov.b r3l,r0l \n"
00170 " rts \n"
00171 );
00172 #endif
00173
00175
00177 int lnp_integrity_write(const unsigned char *data,unsigned char length) {
00178 int r;
00179 #if defined(CONF_MM)
00180 char* buffer_ptr = malloc(length+3);
00181 #else // CONF_MM
00182 char* buffer_ptr = lnp_buffer;
00183 #endif // CONF_MM
00184 unsigned char c = lnp_checksum_copy( buffer_ptr+2, data, length);
00185 lnp_checksum_step( c, buffer_ptr[0]=0xf0 );
00186 lnp_checksum_step( c, buffer_ptr[1]=length );
00187 buffer_ptr[length+2] = c;
00188 r = lnp_logical_write(buffer_ptr,length+3);
00189 #if defined(CONF_MM)
00190 free(buffer_ptr);
00191 #endif // CONF_MM
00192 return r;
00193 }
00194
00196
00198 int lnp_addressing_write(const unsigned char *data,unsigned char length,
00199 unsigned char dest,unsigned char srcport) {
00200 int r;
00201 #if defined(CONF_MM)
00202 char* buffer_ptr = malloc(length+5);
00203 #else // CONF_MM
00204 char* buffer_ptr = lnp_buffer;
00205 #endif // CONF_MM
00206 unsigned char c = lnp_checksum_copy( buffer_ptr+4, data, length );
00207 lnp_checksum_step( c, buffer_ptr[0]=0xf1 );
00208 lnp_checksum_step( c, buffer_ptr[1]=length+2 );
00209 lnp_checksum_step( c, buffer_ptr[2]=dest );
00210 lnp_checksum_step( c, buffer_ptr[3]=
00211 (lnp_hostaddr | (srcport & LNP_PORTMASK)) );
00212 buffer_ptr[length+4] = c;
00213 r = lnp_logical_write(buffer_ptr,length+5);
00214 #if defined(CONF_MM)
00215 free(buffer_ptr);
00216 #endif // CONF_MM
00217 return r;
00218 }
00219
00221 void lnp_receive_packet(const unsigned char *data) {
00222 unsigned char header=*(data++);
00223 unsigned char length=*(data++);
00224 lnp_integrity_handler_t intgh;
00225 lnp_addressing_handler_t addrh;
00226
00227
00228
00229 switch(header) {
00230 case 0xf0:
00231 intgh = lnp_integrity_handler;
00232 if(intgh) {
00233 #ifdef CONF_AUTOSHUTOFF
00234 shutoff_restart();
00235 #endif
00236 intgh(data,length);
00237 }
00238 break;
00239
00240 case 0xf1:
00241 if(length>2) {
00242 unsigned char dest=*(data++);
00243
00244 if(lnp_hostaddr == (dest & LNP_HOSTMASK)) {
00245 unsigned char port=dest & LNP_PORTMASK;
00246 addrh = lnp_addressing_handler[port];
00247 if(addrh) {
00248 unsigned char src=*(data++);
00249 #ifdef CONF_AUTOSHUTOFF
00250 shutoff_restart();
00251 #endif
00252 addrh(data,length-2,src);
00253 }
00254 }
00255 }
00256
00257 }
00258 }
00259
00261 void lnp_integrity_byte(unsigned char b) {
00262 static unsigned char buffer[256+3];
00263 static int bytesRead,endOfData;
00264 static unsigned char chk;
00265
00266 if(lnp_integrity_state==LNPwaitHeader)
00267 bytesRead=0;
00268
00269 buffer[bytesRead++]=b;
00270
00271 switch(lnp_integrity_state) {
00272 case LNPwaitHeader:
00273
00274
00275 if(((b & 0xf8) == 0xf0) || (b == 0x55)) {
00276 #ifdef CONF_VIS
00277 if (lnp_logical_range_is_far()) {
00278 dlcd_show(LCD_IR_UPPER);
00279 dlcd_show(LCD_IR_LOWER);
00280 } else {
00281 dlcd_hide(LCD_IR_UPPER);
00282 dlcd_show(LCD_IR_LOWER);
00283 }
00284 #ifndef CONF_LCD_REFRESH
00285 lcd_refresh();
00286 #endif
00287 #endif
00288
00289 lnp_checksum_init( chk );
00290
00291
00292 if (b == 0x55) {
00293 #if defined(CONF_RCX_PROTOCOL) || defined(CONF_RCX_MESSAGE)
00294
00295 lnp_integrity_state = LNPwaitRMH1;
00296 #else
00297 lnp_integrity_reset();
00298 #endif
00299 } else {
00300 lnp_integrity_state++;
00301 }
00302 }
00303 break;
00304
00305 case LNPwaitLength:
00306 endOfData=b+2;
00307 lnp_integrity_state++;
00308 break;
00309
00310 case LNPwaitData:
00311 if(bytesRead==endOfData)
00312 lnp_integrity_state++;
00313 break;
00314
00315 case LNPwaitCRC:
00316 if(b==chk)
00317 lnp_receive_packet(buffer);
00318 lnp_integrity_reset();
00319 break;
00320
00321 #if defined(CONF_RCX_PROTOCOL) || defined (CONF_RCX_MESSAGE)
00322
00323 case LNPwaitRMH1:
00324 case LNPwaitRMH2:
00325
00326 if ( b == lnp_rcx_header[ lnp_integrity_state-LNPwaitRMH1 ] )
00327 lnp_integrity_state++;
00328 else
00329 lnp_integrity_reset();
00330 break;
00331
00332 case LNPwaitRMH3:
00333 case LNPwaitRMH4:
00334 if ( b == lnp_rcx_remote_op[ lnp_integrity_state-LNPwaitRMH3 ] )
00335 lnp_integrity_state++;
00336 #if defined(CONF_RCX_MESSAGE)
00337 else if ( b == lnp_rcx_msg_op[ lnp_integrity_state-LNPwaitRMH3 ] )
00338 lnp_integrity_state = LNPwaitMH4;
00339 #endif
00340 else
00341 lnp_integrity_reset();
00342 break;
00343
00344 case LNPwaitRB0:
00345 lnp_rcx_temp0 = b;
00346 lnp_integrity_state++;
00347 break;
00348
00349 case LNPwaitRB0I:
00350 if ( (unsigned char)~b == lnp_rcx_temp0 )
00351 lnp_integrity_state++;
00352 else
00353 lnp_integrity_reset();
00354 break;
00355
00356 case LNPwaitRB1:
00357 lnp_rcx_temp1 = b;
00358 lnp_integrity_state++;
00359 break;
00360
00361 case LNPwaitRB1I:
00362 if ( (unsigned char)~b == lnp_rcx_temp1 )
00363 lnp_integrity_state++;
00364 else
00365 lnp_integrity_reset();
00366 break;
00367
00368 case LNPwaitRC:
00369 lnp_rcx_checksum = 0xd2 + lnp_rcx_temp0 + lnp_rcx_temp1;
00370 if ( b == lnp_rcx_checksum )
00371 lnp_integrity_state++;
00372 else
00373 lnp_integrity_reset();
00374 break;
00375
00376 case LNPwaitRCI:
00377
00378 if ( b == (unsigned char)~lnp_rcx_checksum) {
00379 #if defined(CONF_RCX_MESSAGE)
00380
00381 if (lnp_rcx_temp1 & 0x07)
00382 {
00383 lnp_rcx_message = (lnp_rcx_temp1 > 2) ? 3 : lnp_rcx_temp1;
00384 }
00385 else
00386 #endif
00387 {
00388
00389 lnp_remote_handler_t rmth = lnp_remote_handler;
00390 if (rmth)
00391 rmth( (lnp_rcx_temp0<<8)+lnp_rcx_temp1 );
00392 }
00393 }
00394
00395 lnp_integrity_reset();
00396 break;
00397 #endif
00398
00399 #if defined(CONF_RCX_MESSAGE)
00400
00401 case LNPwaitMH3:
00402 case LNPwaitMH4:
00403 if ( b == lnp_rcx_msg_op[ lnp_integrity_state-LNPwaitMH3 ] )
00404 lnp_integrity_state++;
00405 else
00406 lnp_integrity_reset();
00407 break;
00408
00409 case LNPwaitMN:
00410 lnp_rcx_temp0 = b;
00411 lnp_integrity_state++;
00412 break;
00413
00414 case LNPwaitMNC:
00415 if ( (unsigned char)~b == lnp_rcx_temp0 )
00416 lnp_integrity_state++;
00417 else
00418 lnp_integrity_reset();
00419 break;
00420
00421 case LNPwaitMC:
00422 lnp_rcx_temp1 = 0xf7 + lnp_rcx_temp0;
00423
00424 if (b == lnp_rcx_temp1)
00425 lnp_integrity_state++;
00426 else
00427 lnp_integrity_reset();
00428 break;
00429
00430 case LNPwaitMCC:
00431
00432 if ( (unsigned char)~b == lnp_rcx_temp1 )
00433 lnp_rcx_message = lnp_rcx_temp0;
00434
00435 lnp_integrity_reset();
00436 break;
00437 #endif
00438 }
00439
00440 lnp_checksum_step( chk, b );
00441 }
00442
00444 #if defined(CONF_RCX_COMPILER) || defined(CONF_HOST)
00445 void lnp_integrity_reset(void) {
00446 #else
00447 HANDLER_WRAPPER("lnp_integrity_reset","lnp_integrity_reset_core");
00448 void lnp_integrity_reset_core(void) {
00449 #endif
00450 #ifndef CONF_HOST
00451 if(tx_state>TX_IDLE) {
00452 txend_handler();
00453 tx_state=TX_COLL;
00454 } else
00455 #endif
00456 if(lnp_integrity_state!=LNPwaitHeader) {
00457 lnp_integrity_state=LNPwaitHeader;
00458
00459 #ifdef CONF_VIS
00460 dlcd_hide(LCD_IR_LOWER);
00461 dlcd_hide(LCD_IR_UPPER);
00462 #ifndef CONF_LCD_REFRESH
00463 lcd_refresh();
00464 #endif
00465 #endif
00466 }
00467 }
00468
00470
00472 int lnp_integrity_active(void) {
00473 return lnp_integrity_state!=LNPwaitHeader;
00474 }
00475
00477 #if defined(CONF_RCX_COMPILER) || defined(CONF_HOST)
00478 void lnp_timeout_reset(void) {
00479 #else
00480 HANDLER_WRAPPER("lnp_timeout_reset","lnp_timeout_reset_core");
00481 void lnp_timeout_reset_core(void) {
00482 #endif
00483 lnp_timeout_counter=lnp_timeout;
00484 }
00485
00487
00489 void lnp_timeout_set(unsigned short timeout) {
00490 lnp_timeout_counter=lnp_timeout=timeout;
00491 }
00492
00494
00496 void lnp_init(void) {
00497 int k;
00498
00499 for(k=1; k<=LNP_PORTMASK; k++)
00500 lnp_addressing_handler[k]=LNP_DUMMY_ADDRESSING;
00501 lnp_integrity_handler=LNP_DUMMY_INTEGRITY;
00502
00503 #if defined(CONF_RCX_PROTOCOL)
00504 lnp_remote_handler=LNP_DUMMY_REMOTE;
00505 #endif
00506 #if defined(CONF_RCX_MESSAGE)
00507 clear_msg();
00508 #endif
00509 }
00510
00511 #ifdef CONF_RCX_MESSAGE
00512 wakeup_t msg_received(wakeup_t m) {
00513 return (m == 0 ? lnp_rcx_message != 0 : lnp_rcx_message == m);
00514 }
00515
00517
00519 int send_msg(unsigned char msg)
00520 {
00521 int r;
00522 #if defined(CONF_MM)
00523 char* buffer_ptr = malloc(9);
00524 #else // CONF_MM
00525 char* buffer_ptr = lnp_buffer;
00526 #endif // CONF_MM
00527 buffer_ptr[0]=0x55;
00528 buffer_ptr[1]=0xff;
00529 buffer_ptr[2]=0x00;
00530 buffer_ptr[3]=0xf7;
00531 buffer_ptr[4]=0x08;
00532 buffer_ptr[5]=msg;
00533 buffer_ptr[6]=(unsigned char) (0xff-msg);
00534 buffer_ptr[7]=(unsigned char) (0xf7+msg);
00535 buffer_ptr[8]=(unsigned char) (0x08-msg);
00536 r = lnp_logical_write(buffer_ptr,9);
00537 #if defined(CONF_MM)
00538 free(buffer_ptr);
00539 #endif // CONF_MM
00540 return r;
00541 }
00542 #endif
00543
00544 #endif // CONF_LNP