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 #include <sys/program.h>
00043
00044 #ifdef CONF_PROGRAM
00045
00046 #include <sys/tm.h>
00047 #include <string.h>
00048 #include <semaphore.h>
00049 #include <unistd.h>
00050 #include <stdlib.h>
00051
00052 #include <sys/lnp.h>
00053 #include <sys/lnp-logical.h>
00054 #include <sys/dmotor.h>
00055 #include <sys/dsensor.h>
00056 #include <sys/mm.h>
00057 #include <sys/battery.h>
00058 #include <dsound.h>
00059 #include <remote.h>
00060
00061 #include <conio.h>
00062
00064
00065
00066
00068
00069 volatile unsigned cprog;
00070
00072
00073
00074
00076
00077 const unsigned char min_length[]={
00078 1,
00079 2,
00080 13,
00081 8,
00082 4,
00083 2,
00084 2,
00085 2
00086 };
00087
00088 static program_t programs[PROG_MAX];
00089
00090 static unsigned char* buffer_ptr;
00091 volatile unsigned char packet_len;
00092 volatile unsigned char packet_src;
00093
00094 static sem_t packet_sem;
00095
00096 #if 0
00097 #define debugs(a) { cputs(a); msleep(500); }
00098 #define debugw(a) { cputw(a); msleep(500); }
00099 #else
00100 #define debugs(a)
00101 #define debugw(a)
00102 #endif
00103
00104
00105 int lrkey_handler(unsigned int etype, unsigned int key);
00106
00108
00109
00110
00112
00114
00115 int program_valid(unsigned nr) {
00116 program_t *prog=programs+nr;
00117
00118 return (nr < PROG_MAX) &&
00119 (prog->text_size>0) &&
00120 (prog->text_size+prog->data_size==prog->downloaded);
00121 }
00122
00124 static void program_run(unsigned nr) {
00125 if(program_valid(nr)) {
00126 program_t *prog=programs+nr;
00127
00128
00129
00130 memcpy(prog->data,prog->data_orig,prog->data_size);
00131 memset(prog->bss,0,prog->bss_size);
00132
00133 execi((void*) (((char*)prog->text)
00134 + prog->start ),
00135 0,0,prog->prio,prog->stack_size);
00136 }
00137 }
00138
00140
00142 static void packet_producer(const unsigned char *data,
00143 unsigned char length,
00144 unsigned char src) {
00145
00146
00147 if(packet_len>0 || length==0)
00148 return;
00149
00150 if (buffer_ptr != 0)
00151 return;
00152
00153 buffer_ptr = malloc(length);
00154 memcpy(buffer_ptr,data,length);
00155 packet_len=length;
00156 packet_src=src;
00157 sem_post(&packet_sem);
00158 }
00159
00161 static int packet_consumer(int argc, char *argv[]) {
00162 packet_cmd_t cmd;
00163 unsigned char nr=0;
00164 program_t *prog=programs;
00165 const static unsigned char acknowledge=CMDacknowledge;
00166 char msg[8];
00167
00168 while (!shutdown_requested()) {
00169
00170
00171 packet_len=0;
00172 free(buffer_ptr);
00173 buffer_ptr = 0;
00174 if (sem_wait(&packet_sem) != -1) {
00175 if (buffer_ptr == 0)
00176 continue;
00177
00178 debugw(*(size_t*)buffer_ptr);
00179
00180
00181
00182 cmd=buffer_ptr[0];
00183 if (cmd>=CMDlast || packet_len<min_length[cmd])
00184 continue;
00185
00186
00187 if (cmd==CMDirmode) {
00188 if (buffer_ptr[1]==0) {
00189 debugs("nearmodeIR");
00190 lnp_logical_range(0);
00191 debugs("OK");
00192 lnp_addressing_write(&acknowledge,1,packet_src,0);
00193 } else {
00194 debugs("farmodeIR");
00195 lnp_logical_range(1);
00196 debugs("OK");
00197 lnp_addressing_write(&acknowledge,1,packet_src,0);
00198 }
00199 continue;
00200 }
00201
00202
00203 if (cmd == CMDsethost) {
00204
00205 lnp_addressing_write(&acknowledge,1,packet_src,0);
00206 lnp_set_hostaddr(buffer_ptr[1]);
00207 continue;
00208 }
00209
00210
00211 if((cmd > CMDacknowledge) && (cmd <= CMDrun)) {
00212 nr = buffer_ptr[1];
00213 if(nr > PROG_MAX)
00214 continue;
00215 #ifndef CONF_VIS
00216 cputc_hex_0(nr+1);
00217 #endif
00218 }
00219
00220 debugw(nr);
00221 prog = programs+nr;
00222
00223 switch( cmd ) {
00224 case CMDdelete:
00225 debugs("dele");
00226
00227 if(nb_tasks <= nb_system_tasks) {
00228 if(prog->text)
00229 free(prog->text);
00230 memset(prog,0,sizeof(program_t));
00231
00232 #ifndef CONF_VIS
00233 if(nr == cprog)
00234 cputc_0('-');
00235 #endif
00236 debugs("OK");
00237
00238 lnp_addressing_write(&acknowledge,1,packet_src,0);
00239 }
00240 break;
00241
00242 case CMDcreate:
00243 debugs("crea");
00244 if(!prog->text) {
00245 memcpy(&(prog->text_size),buffer_ptr+2,11);
00246
00247 if((prog->text=malloc(prog->text_size+
00248 2*prog->data_size+
00249 prog->bss_size ))) {
00250 prog->data=prog->text+prog->text_size;
00251 prog->bss=prog->data+prog->data_size;
00252 prog->data_orig=prog->bss +prog->bss_size;
00253 prog->downloaded=0;
00254
00255 debugs("OK");
00256
00257 cputw(0);
00258 cprog = nr;
00259
00260 msg[0]=CMDacknowledge;
00261 msg[1]=nr;
00262 memcpy(msg+2,prog,6);
00263 lnp_addressing_write(msg,8,packet_src,0);
00264 } else
00265 memset(prog,0,sizeof(program_t));
00266 }
00267 break;
00268
00269 case CMDdata:
00270 debugs("data");
00271 if(prog->text && !program_valid(nr)) {
00272 size_t offset=*(size_t*)(buffer_ptr+2);
00273 if(offset<=prog->downloaded) {
00274 if(offset==prog->downloaded) {
00275 memcpy(prog->text+offset,buffer_ptr+4,packet_len-4);
00276 prog->downloaded+=packet_len-4;
00277
00278 if(program_valid(nr)) {
00279
00280
00281 memcpy(prog->data_orig,prog->data,prog->data_size);
00282 cls();
00283 } else
00284 cputw(prog->downloaded);
00285 debugs("OK");
00286 } else
00287 debugs("OLD");
00288
00289 lnp_addressing_write(&acknowledge,1,packet_src,0);
00290 }
00291 }
00292 break;
00293
00294 case CMDrun:
00295 debugs("run");
00296 if(program_valid(nr)) {
00297 cprog = nr;
00298 program_stop(0);
00299 program_run(nr);
00300
00301 debugs("OK");
00302 lnp_addressing_write(&acknowledge,1,packet_src,0);
00303 }
00304 break;
00305
00306 default:
00307 debugs("error");
00308 }
00309 }
00310 }
00311 free(buffer_ptr);
00312 return 0;
00313 }
00314
00316 void program_stop(int flag) {
00317 int count_down = 40;
00318
00319
00320 shutdown_tasks(T_USER);
00321
00322 while (--count_down && (nb_tasks > nb_system_tasks)) {
00323 if (flag)
00324 cputs("STOP");
00325 msleep(100);
00326 }
00327
00328 if (nb_tasks > nb_system_tasks) {
00329
00330 if (flag) {
00331 cputs("KILL");
00332
00333 lcd_refresh();
00334 }
00335 killall(PRIO_HIGHEST-1);
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 #ifdef CONF_DSOUND
00347 dsound_stop();
00348 #endif
00349 #ifdef CONF_DMOTOR
00350 dm_init();
00351 #endif
00352 #ifdef CONF_DSENSOR
00353 ds_init();
00354 #endif
00355 lnp_init();
00356 #ifdef CONF_LR_HANDLER
00357
00358 lr_init();
00359 lr_set_handler(lrkey_handler);
00360 #endif
00361 }
00362
00364 int key_handler(int argc, char *argv[]) {
00365 int c;
00366
00367 #ifndef CONF_VIS
00368 cputc_0('-');
00369 #endif
00370
00371 while (!shutdown_requested()) {
00372 int clear=0;
00373 c=getchar();
00374
00375 gotkey:
00376
00377 debugs("key "); debugw(c);
00378 debugs("task"); debugw(nb_tasks);
00379
00380 switch(c) {
00381 case KEY_ONOFF:
00382 cputs("OFF");
00383
00384 shutdown_tasks(T_USER | T_KERNEL);
00385
00386 ctid->tflags &= (~T_SHUTDOWN);
00387
00388 clear = 50;
00389 while (--clear && (nb_tasks > 2))
00390 msleep(100);
00391
00392 if (nb_tasks > 2)
00393 killall(PRIO_HIGHEST);
00394
00395 ctid->tflags |= T_SHUTDOWN;
00396 break;
00397
00398 case KEY_RUN:
00399
00400 if(nb_tasks > nb_system_tasks) {
00401
00402 clear=1;
00403 program_stop(1);
00404 } else if(program_valid(cprog)) {
00405 program_stop(0);
00406 program_run(cprog);
00407 } else {
00408 cputs("NONE");
00409 clear=1;
00410 }
00411 break;
00412
00413 case KEY_PRGM:
00414
00415 if(nb_tasks <= nb_system_tasks) {
00416 int i;
00417 for(i=0; i<PROG_MAX; i++) {
00418 if( (++cprog)>=PROG_MAX)
00419 cprog=0;
00420 if(program_valid(cprog))
00421 break;
00422 }
00423 if(i==PROG_MAX) {
00424 cputs("NONE");
00425 clear=1;
00426 #ifndef CONF_VIS
00427 cputc_0('-');
00428 }
00429 else
00430 cputc_hex_0(cprog+1);
00431 #else
00432 }
00433 #endif
00434
00435 }
00436 break;
00437 case KEY_VIEW:
00438
00439 if (nb_tasks > nb_system_tasks)
00440 break;
00441
00442
00443
00444
00445
00446
00447
00448 cputs("addr");
00449 if ((c = getchar()) != KEY_VIEW) goto gotkey;
00450 cputw(lnp_hostaddr);
00451 while ((c = getchar()) == KEY_PRGM) {
00452 lnp_hostaddr += 0x10;
00453 lnp_hostaddr &= CONF_LNP_HOSTMASK;
00454 cputw(lnp_hostaddr);
00455 }
00456 if (c != KEY_VIEW) goto gotkey;
00457 if (program_valid(cprog)) {
00458 cputs("dele");
00459 if ((c = getchar()) != KEY_VIEW && c != KEY_PRGM) goto gotkey;
00460 if (c == KEY_PRGM) {
00461 program_t *prog=programs+cprog;
00462 if (prog->text)
00463 free(prog->text);
00464 memset(prog,0,sizeof(program_t));
00465 cputc_0('-');
00466 }
00467 }
00468
00469 cputs("free");
00470 if ((c = getchar()) != KEY_VIEW) goto gotkey;
00471 lcd_int(mm_free_mem());
00472 if ((c = getchar()) != KEY_VIEW) goto gotkey;
00473 cputw(mm_free_mem());
00474 if ((c = getchar()) != KEY_VIEW) goto gotkey;
00475
00476 #if defined(CONF_DSENSOR)
00477 cputs("batt");
00478 if ((c = getchar()) != KEY_VIEW) goto gotkey;
00479 lcd_int(get_battery_mv());
00480 if ((c = getchar()) != KEY_VIEW) goto gotkey;
00481 #endif // CONF_DSENSOR
00482
00483 clear=1;
00484 break;
00485 }
00486
00487 if(clear) {
00488 wait_event(dkey_released,KEY_ANY);
00489 cls();
00490 }
00491 }
00492 return 0;
00493 }
00494
00495 #if defined(CONF_LR_HANDLER)
00496
00497 int lrkey_handler(unsigned int etype, unsigned int key) {
00498 unsigned char pnr = 0;
00499
00500
00501
00502 if(key == LRKEY_STOP && etype == LREVT_KEYON && nb_tasks > nb_system_tasks) {
00503 program_stop(1);
00504 return 1;
00505 }
00506
00507
00508 if(nb_tasks <= nb_system_tasks) {
00509
00510 if (etype == LREVT_KEYON) {
00511 switch (key) {
00512 #ifdef CONF_DSOUND
00513 case LRKEY_BEEP:
00514
00515 dsound_system(0);
00516 break;
00517 #endif // CONF_DSOUND
00518
00519 case LRKEY_P5:
00520 pnr++;
00521
00522 case LRKEY_P4:
00523 pnr++;
00524
00525 case LRKEY_P3:
00526 pnr++;
00527
00528 case LRKEY_P2:
00529 pnr++;
00530
00531 case LRKEY_P1:
00532
00533 if(program_valid(pnr))
00534 {
00535 cprog = pnr;
00536
00537 program_stop(0);
00538 #ifdef CONF_VIS
00539 cputc_hex_0(pnr+1);
00540 #ifndef CONF_LCD_REFRESH
00541 lcd_refresh();
00542 #endif
00543 #endif
00544
00545 program_run(pnr);
00546 } else {
00547
00548 cputs("NONE");
00549 }
00550 break;
00551
00552 #if defined(CONF_DMOTOR)
00553
00554 case LRKEY_A1:
00555
00556 motor_a_dir(fwd);
00557 break;
00558 case LRKEY_A2:
00559
00560 motor_a_dir(rev);
00561 break;
00562 case LRKEY_B1:
00563
00564 motor_b_dir(fwd);
00565 break;
00566 case LRKEY_B2:
00567
00568 motor_b_dir(rev);
00569 break;
00570 case LRKEY_C1:
00571
00572 motor_c_dir(fwd);
00573 break;
00574 case LRKEY_C2:
00575
00576 motor_c_dir(rev);
00577 break;
00578 #endif // CONF_DMOTOR
00579 default:
00580
00581 return 0;
00582 }
00583 #ifndef CONF_LCD_REFRESH
00584 lcd_refresh();
00585 #endif
00586
00587 return 1;
00588 }
00589
00590
00591 if (etype == LREVT_KEYOFF) {
00592 switch (key) {
00593 #if defined(CONF_DMOTOR)
00594 case LRKEY_A1:
00595 case LRKEY_A2:
00596
00597 motor_a_dir(brake);
00598 break;
00599 case LRKEY_B1:
00600 case LRKEY_B2:
00601
00602 motor_b_dir(brake);
00603 break;
00604 case LRKEY_C1:
00605 case LRKEY_C2:
00606
00607 motor_c_dir(brake);
00608 break;
00609 #endif // CONF_DMOTOR
00610 case LRKEY_P1:
00611 case LRKEY_P2:
00612 case LRKEY_P3:
00613 case LRKEY_P4:
00614 case LRKEY_P5:
00615 case LRKEY_STOP:
00616
00617 cls();
00618 break;
00619 default:
00620 return 0;
00621 }
00622
00623 return 1;
00624 }
00625 }
00626
00627 #ifndef CONF_LCD_REFRESH
00628 lcd_refresh();
00629 #endif
00630
00631 return 0;
00632 }
00633 #endif
00634
00636
00638 void program_init() {
00639 packet_len=0;
00640 sem_init(&packet_sem,0,0);
00641 execi(&packet_consumer,0,0,PRIO_HIGHEST,DEFAULT_STACK_SIZE);
00642 execi(&key_handler,0,0,PRIO_HIGHEST,DEFAULT_STACK_SIZE);
00643
00644 #ifdef CONF_LR_HANDLER
00645
00646 lr_startup();
00647 lr_set_handler(lrkey_handler);
00648 #endif
00649
00650 lnp_addressing_set_handler(0,&packet_producer);
00651 buffer_ptr = 0;
00652 }
00653
00655
00657 void program_shutdown() {
00658 lnp_addressing_set_handler(0,LNP_DUMMY_ADDRESSING);
00659 sem_destroy(&packet_sem);
00660
00661 #ifdef CONF_LR_HANDLER
00662 lr_shutdown();
00663 #endif
00664 }
00665
00666 #endif // CONF_PROGRAM