From 4bf0dee4cf42426151f9e0f7ce12b403df57b1c9 Mon Sep 17 00:00:00 2001 From: Rene Hopf Date: Wed, 13 Jan 2016 22:53:47 +0100 Subject: [PATCH] cleanup --- memtemp/data.txt | 1992 ------------------------------------------- memtemp/memtemp.c | 464 ---------- memtemp/sserial.sr | Bin 84359 -> 0 bytes memtemp/tocdump.c | 95 --- memtemp/tocdump.txt | 306 ------- sim/gp | 5 - sim/pwm.html | 403 --------- sim/sim.cpp | 410 --------- sim/sim.h | 616 ------------- tools/checkcrc.py | 12 - 10 files changed, 4303 deletions(-) delete mode 100644 memtemp/data.txt delete mode 100644 memtemp/memtemp.c delete mode 100644 memtemp/sserial.sr delete mode 100644 memtemp/tocdump.c delete mode 100644 memtemp/tocdump.txt delete mode 100644 sim/gp delete mode 100644 sim/pwm.html delete mode 100644 sim/sim.cpp delete mode 100644 sim/sim.h delete mode 100755 tools/checkcrc.py diff --git a/memtemp/data.txt b/memtemp/data.txt deleted file mode 100644 index 45dffd98..00000000 --- a/memtemp/data.txt +++ /dev/null @@ -1,1992 +0,0 @@ -Get LBP cookie -Set Command timeout -Set LBPstatus -Get LBP status -UnitNumberRPC -Get card name char0 -Get card name char1 -Get card name char2 -Get card name char3 -Set Reserved stuff -DiscoveryRPC -read 0x90 from 0xa584 -read 0xa2 from 0xa585 -read 0xb0 from 0xa290 -read 0xb0 from 0xa290 -read 0x0 from 0xa291 -read 0x0 from 0xa292 -read 0x0 from 0xa293 -read 0x53 from 0xa294 -read 0x74 from 0xa295 -read 0x61 from 0xa296 -read 0x6e from 0xa297 -read 0x64 from 0xa298 -read 0x61 from 0xa299 -read 0x72 from 0xa29a -read 0x64 from 0xa29b -read 0x0 from 0xa29c -read 0x9e from 0xa586 -read 0xa2 from 0xa587 -read 0xb0 from 0xa29e -read 0xb0 from 0xa29e -read 0x0 from 0xa29f -read 0x1 from 0xa2a0 -read 0x0 from 0xa2a1 -read 0x49 from 0xa2a2 -read 0x4f from 0xa2a3 -read 0x5f from 0xa2a4 -read 0x53 from 0xa2a5 -read 0x70 from 0xa2a6 -read 0x69 from 0xa2a7 -read 0x6e from 0xa2a8 -read 0x0 from 0xa2a9 -read 0xaa from 0xa588 -read 0xa2 from 0xa589 -read 0xb0 from 0xa2aa -read 0xb0 from 0xa2aa -read 0x1 from 0xa2ab -read 0x1 from 0xa2ac -read 0x0 from 0xa2ad -read 0x49 from 0xa2ae -read 0x4f from 0xa2af -read 0x5f from 0xa2b0 -read 0x41 from 0xa2b1 -read 0x6e from 0xa2b2 -read 0x61 from 0xa2b3 -read 0x5f from 0xa2b4 -read 0x53 from 0xa2b5 -read 0x70 from 0xa2b6 -read 0x69 from 0xa2b7 -read 0x6e from 0xa2b8 -read 0x0 from 0xa2b9 -read 0xba from 0xa58a -read 0xa2 from 0xa58b -read 0xb0 from 0xa2ba -read 0xb0 from 0xa2ba -read 0x2 from 0xa2bb -read 0x1 from 0xa2bc -read 0x0 from 0xa2bd -read 0x49 from 0xa2be -read 0x4f from 0xa2bf -read 0x5f from 0xa2c0 -read 0x45 from 0xa2c1 -read 0x6e from 0xa2c2 -read 0x63 from 0xa2c3 -read 0x5f from 0xa2c4 -read 0x41 from 0xa2c5 -read 0x6e from 0xa2c6 -read 0x61 from 0xa2c7 -read 0x5f from 0xa2c8 -read 0x53 from 0xa2c9 -read 0x70 from 0xa2ca -read 0x69 from 0xa2cb -read 0x6e from 0xa2cc -read 0x5f from 0xa2cd -read 0x46 from 0xa2ce -read 0x56 from 0xa2cf -read 0x0 from 0xa2d0 -read 0xd2 from 0xa58c -read 0xa2 from 0xa58d -read 0xa0 from 0xa2d2 -read 0xa0 from 0xa2d2 -read 0x20 from 0xa2d3 -read 0x1 from 0xa2d4 -read 0x0 from 0xa2d5 -read 0x0 from 0xa2d6 -read 0x0 from 0xa2d7 -read 0x0 from 0xa2d8 -read 0x0 from 0xa2d9 -read 0x0 from 0xa2da -read 0x0 from 0xa2db -read 0x0 from 0xa2dc -read 0x0 from 0xa2dd -read 0x8 from 0xa2de -read 0x8 from 0xa2df -read 0x4e from 0xa2e0 -read 0x6f from 0xa2e1 -read 0x6e from 0xa2e2 -read 0x65 from 0xa2e3 -read 0x0 from 0xa2e4 -read 0x49 from 0xa2e5 -read 0x6e from 0xa2e6 -read 0x70 from 0xa2e7 -read 0x75 from 0xa2e8 -read 0x74 from 0xa2e9 -read 0x0 from 0xa2ea -read 0xec from 0xa58e -read 0xa2 from 0xa58f -read 0xa0 from 0xa2ec -read 0xa0 from 0xa2ec -read 0x10 from 0xa2ed -read 0x1 from 0xa2ee -read 0x80 from 0xa2ef -read 0x0 from 0xa2f0 -read 0x0 from 0xa2f1 -read 0x0 from 0xa2f2 -read 0x0 from 0xa2f3 -read 0x0 from 0xa2f4 -read 0x0 from 0xa2f5 -read 0x0 from 0xa2f6 -read 0x0 from 0xa2f7 -read 0x0 from 0xa2f8 -read 0x8 from 0xa2f9 -read 0x4e from 0xa2fa -read 0x6f from 0xa2fb -read 0x6e from 0xa2fc -read 0x65 from 0xa2fd -read 0x0 from 0xa2fe -read 0x4f from 0xa2ff -read 0x75 from 0xa300 -read 0x74 from 0xa301 -read 0x70 from 0xa302 -read 0x75 from 0xa303 -read 0x74 from 0xa304 -read 0x0 from 0xa305 -read 0x6 from 0xa590 -read 0xa3 from 0xa591 -read 0xa0 from 0xa306 -read 0xa0 from 0xa306 -read 0x10 from 0xa307 -read 0x2 from 0xa308 -read 0x80 from 0xa309 -read 0x0 from 0xa30a -read 0x0 from 0xa30b -read 0x0 from 0xa30c -read 0x0 from 0xa30d -read 0x0 from 0xa30e -read 0x0 from 0xa30f -read 0xc8 from 0xa310 -read 0x42 from 0xa311 -read 0x40 from 0xa312 -read 0x8 from 0xa313 -read 0x50 from 0xa314 -read 0x65 from 0xa315 -read 0x72 from 0xa316 -read 0x63 from 0xa317 -read 0x65 from 0xa318 -read 0x6e from 0xa319 -read 0x74 from 0xa31a -read 0x0 from 0xa31b -read 0x53 from 0xa31c -read 0x70 from 0xa31d -read 0x69 from 0xa31e -read 0x6e from 0xa31f -read 0x4f from 0xa320 -read 0x75 from 0xa321 -read 0x74 from 0xa322 -read 0x0 from 0xa323 -read 0x24 from 0xa592 -read 0xa3 from 0xa593 -read 0xa0 from 0xa324 -read 0xa0 from 0xa324 -read 0x8 from 0xa325 -read 0x7 from 0xa326 -read 0x80 from 0xa327 -read 0x0 from 0xa328 -read 0x0 from 0xa329 -read 0x0 from 0xa32a -read 0x0 from 0xa32b -read 0x0 from 0xa32c -read 0x0 from 0xa32d -read 0x0 from 0xa32e -read 0x0 from 0xa32f -read 0x42 from 0xa330 -read 0x8 from 0xa331 -read 0x4e from 0xa332 -read 0x6f from 0xa333 -read 0x6e from 0xa334 -read 0x65 from 0xa335 -read 0x0 from 0xa336 -read 0x53 from 0xa337 -read 0x70 from 0xa338 -read 0x69 from 0xa339 -read 0x6e from 0xa33a -read 0x45 from 0xa33b -read 0x6e from 0xa33c -read 0x61 from 0xa33d -read 0x0 from 0xa33e -read 0x40 from 0xa594 -read 0xa3 from 0xa595 -read 0xa0 from 0xa340 -read 0xa0 from 0xa340 -read 0x8 from 0xa341 -read 0x7 from 0xa342 -read 0x80 from 0xa343 -read 0x0 from 0xa344 -read 0x0 from 0xa345 -read 0x0 from 0xa346 -read 0x0 from 0xa347 -read 0x0 from 0xa348 -read 0x0 from 0xa349 -read 0x0 from 0xa34a -read 0x0 from 0xa34b -read 0x43 from 0xa34c -read 0x8 from 0xa34d -read 0x4e from 0xa34e -read 0x6f from 0xa34f -read 0x6e from 0xa350 -read 0x65 from 0xa351 -read 0x0 from 0xa352 -read 0x53 from 0xa353 -read 0x70 from 0xa354 -read 0x69 from 0xa355 -read 0x6e from 0xa356 -read 0x44 from 0xa357 -read 0x69 from 0xa358 -read 0x72 from 0xa359 -read 0x0 from 0xa35a -read 0x5c from 0xa596 -read 0xa3 from 0xa597 -read 0xa0 from 0xa35c -read 0xa0 from 0xa35c -read 0x8 from 0xa35d -read 0x2 from 0xa35e -read 0x0 from 0xa35f -read 0x0 from 0xa360 -read 0x0 from 0xa361 -read 0x0 from 0xa362 -read 0x0 from 0xa363 -read 0x33 from 0xa364 -read 0x33 from 0xa365 -read 0x11 from 0xa366 -read 0x42 from 0xa367 -read 0x10 from 0xa368 -read 0x8 from 0xa369 -read 0x56 from 0xa36a -read 0x6f from 0xa36b -read 0x6c from 0xa36c -read 0x74 from 0xa36d -read 0x73 from 0xa36e -read 0x0 from 0xa36f -read 0x41 from 0xa370 -read 0x6e from 0xa371 -read 0x61 from 0xa372 -read 0x6c from 0xa373 -read 0x6f from 0xa374 -read 0x67 from 0xa375 -read 0x49 from 0xa376 -read 0x6e from 0xa377 -read 0x30 from 0xa378 -read 0x0 from 0xa379 -read 0x7a from 0xa598 -read 0xa3 from 0xa599 -read 0xa0 from 0xa37a -read 0xa0 from 0xa37a -read 0x8 from 0xa37b -read 0x2 from 0xa37c -read 0x0 from 0xa37d -read 0x0 from 0xa37e -read 0x0 from 0xa37f -read 0x0 from 0xa380 -read 0x0 from 0xa381 -read 0x33 from 0xa382 -read 0x33 from 0xa383 -read 0x11 from 0xa384 -read 0x42 from 0xa385 -read 0x11 from 0xa386 -read 0x8 from 0xa387 -read 0x56 from 0xa388 -read 0x6f from 0xa389 -read 0x6c from 0xa38a -read 0x74 from 0xa38b -read 0x73 from 0xa38c -read 0x0 from 0xa38d -read 0x41 from 0xa38e -read 0x6e from 0xa38f -read 0x61 from 0xa390 -read 0x6c from 0xa391 -read 0x6f from 0xa392 -read 0x67 from 0xa393 -read 0x49 from 0xa394 -read 0x6e from 0xa395 -read 0x31 from 0xa396 -read 0x0 from 0xa397 -read 0x98 from 0xa59a -read 0xa3 from 0xa59b -read 0xa0 from 0xa398 -read 0xa0 from 0xa398 -read 0x8 from 0xa399 -read 0x2 from 0xa39a -read 0x0 from 0xa39b -read 0x0 from 0xa39c -read 0x0 from 0xa39d -read 0x0 from 0xa39e -read 0x0 from 0xa39f -read 0x33 from 0xa3a0 -read 0x33 from 0xa3a1 -read 0x11 from 0xa3a2 -read 0x42 from 0xa3a3 -read 0x12 from 0xa3a4 -read 0x8 from 0xa3a5 -read 0x56 from 0xa3a6 -read 0x6f from 0xa3a7 -read 0x6c from 0xa3a8 -read 0x74 from 0xa3a9 -read 0x73 from 0xa3aa -read 0x0 from 0xa3ab -read 0x41 from 0xa3ac -read 0x6e from 0xa3ad -read 0x61 from 0xa3ae -read 0x6c from 0xa3af -read 0x6f from 0xa3b0 -read 0x67 from 0xa3b1 -read 0x49 from 0xa3b2 -read 0x6e from 0xa3b3 -read 0x32 from 0xa3b4 -read 0x0 from 0xa3b5 -read 0xb6 from 0xa59c -read 0xa3 from 0xa59d -read 0xa0 from 0xa3b6 -read 0xa0 from 0xa3b6 -read 0x8 from 0xa3b7 -read 0x2 from 0xa3b8 -read 0x0 from 0xa3b9 -read 0x0 from 0xa3ba -read 0x0 from 0xa3bb -read 0x0 from 0xa3bc -read 0x0 from 0xa3bd -read 0x33 from 0xa3be -read 0x33 from 0xa3bf -read 0x11 from 0xa3c0 -read 0x42 from 0xa3c1 -read 0x13 from 0xa3c2 -read 0x8 from 0xa3c3 -read 0x56 from 0xa3c4 -read 0x6f from 0xa3c5 -read 0x6c from 0xa3c6 -read 0x74 from 0xa3c7 -read 0x73 from 0xa3c8 -read 0x0 from 0xa3c9 -read 0x41 from 0xa3ca -read 0x6e from 0xa3cb -read 0x61 from 0xa3cc -read 0x6c from 0xa3cd -read 0x6f from 0xa3ce -read 0x67 from 0xa3cf -read 0x49 from 0xa3d0 -read 0x6e from 0xa3d1 -read 0x33 from 0xa3d2 -read 0x0 from 0xa3d3 -read 0xd4 from 0xa59e -read 0xa3 from 0xa59f -read 0xa0 from 0xa3d4 -read 0xa0 from 0xa3d4 -read 0x10 from 0xa3d5 -read 0x2 from 0xa3d6 -read 0x0 from 0xa3d7 -read 0x0 from 0xa3d8 -read 0x0 from 0xa3d9 -read 0x0 from 0xa3da -read 0x0 from 0xa3db -read 0x33 from 0xa3dc -read 0x33 from 0xa3dd -read 0x11 from 0xa3de -read 0x42 from 0xa3df -read 0x18 from 0xa3e0 -read 0xa from 0xa3e1 -read 0x56 from 0xa3e2 -read 0x6f from 0xa3e3 -read 0x6c from 0xa3e4 -read 0x74 from 0xa3e5 -read 0x73 from 0xa3e6 -read 0x0 from 0xa3e7 -read 0x46 from 0xa3e8 -read 0x69 from 0xa3e9 -read 0x65 from 0xa3ea -read 0x6c from 0xa3eb -read 0x64 from 0xa3ec -read 0x56 from 0xa3ed -read 0x6f from 0xa3ee -read 0x6c from 0xa3ef -read 0x74 from 0xa3f0 -read 0x61 from 0xa3f1 -read 0x67 from 0xa3f2 -read 0x65 from 0xa3f3 -read 0x0 from 0xa3f4 -read 0xf6 from 0xa5a0 -read 0xa3 from 0xa5a1 -read 0xa0 from 0xa3f6 -read 0xa0 from 0xa3f6 -read 0x8 from 0xa3f7 -read 0x8 from 0xa3f8 -read 0x0 from 0xa3f9 -read 0x0 from 0xa3fa -read 0x0 from 0xa3fb -read 0x0 from 0xa3fc -read 0x0 from 0xa3fd -read 0x0 from 0xa3fe -read 0x0 from 0xa3ff -read 0x0 from 0xa400 -read 0x0 from 0xa401 -read 0xa0 from 0xa402 -read 0x9 from 0xa403 -read 0x43 from 0xa404 -read 0x6f from 0xa405 -read 0x75 from 0xa406 -read 0x6e from 0xa407 -read 0x74 from 0xa408 -read 0x73 from 0xa409 -read 0x0 from 0xa40a -read 0x45 from 0xa40b -read 0x6e from 0xa40c -read 0x63 from 0xa40d -read 0x30 from 0xa40e -read 0x0 from 0xa40f -read 0x10 from 0xa5a2 -read 0xa4 from 0xa5a3 -read 0xa0 from 0xa410 -read 0xa0 from 0xa410 -read 0x8 from 0xa411 -read 0x8 from 0xa412 -read 0x0 from 0xa413 -read 0x0 from 0xa414 -read 0x0 from 0xa415 -read 0x0 from 0xa416 -read 0x0 from 0xa417 -read 0x0 from 0xa418 -read 0x0 from 0xa419 -read 0x0 from 0xa41a -read 0x0 from 0xa41b -read 0xa2 from 0xa41c -read 0x9 from 0xa41d -read 0x43 from 0xa41e -read 0x6f from 0xa41f -read 0x75 from 0xa420 -read 0x6e from 0xa421 -read 0x74 from 0xa422 -read 0x73 from 0xa423 -read 0x0 from 0xa424 -read 0x45 from 0xa425 -read 0x6e from 0xa426 -read 0x63 from 0xa427 -read 0x31 from 0xa428 -read 0x0 from 0xa429 -read 0x2a from 0xa5a4 -read 0xa4 from 0xa5a5 -read 0xa0 from 0xa42a -read 0xa0 from 0xa42a -read 0x10 from 0xa42b -read 0x2 from 0xa42c -read 0x80 from 0xa42d -read 0x0 from 0xa42e -read 0x0 from 0xa42f -read 0x0 from 0xa430 -read 0x0 from 0xa431 -read 0x0 from 0xa432 -read 0x0 from 0xa433 -read 0x0 from 0xa434 -read 0x0 from 0xa435 -read 0x5c from 0xa436 -read 0x9 from 0xa437 -read 0x4e from 0xa438 -read 0x6f from 0xa439 -read 0x6e from 0xa43a -read 0x65 from 0xa43b -read 0x0 from 0xa43c -read 0x53 from 0xa43d -read 0x77 from 0xa43e -read 0x52 from 0xa43f -read 0x65 from 0xa440 -read 0x76 from 0xa441 -read 0x69 from 0xa442 -read 0x73 from 0xa443 -read 0x69 from 0xa444 -read 0x6f from 0xa445 -read 0x6e from 0xa446 -read 0x0 from 0xa447 -read 0x48 from 0xa5a6 -read 0xa4 from 0xa5a7 -read 0xa0 from 0xa448 -read 0xa0 from 0xa448 -read 0x10 from 0xa449 -read 0x2 from 0xa44a -read 0x80 from 0xa44b -read 0x0 from 0xa44c -read 0x0 from 0xa44d -read 0x0 from 0xa44e -read 0x0 from 0xa44f -read 0x0 from 0xa450 -read 0x0 from 0xa451 -read 0x0 from 0xa452 -read 0x0 from 0xa453 -read 0x74 from 0xa454 -read 0x9 from 0xa455 -read 0x4e from 0xa456 -read 0x6f from 0xa457 -read 0x6e from 0xa458 -read 0x65 from 0xa459 -read 0x0 from 0xa45a -read 0x48 from 0xa45b -read 0x77 from 0xa45c -read 0x52 from 0xa45d -read 0x65 from 0xa45e -read 0x76 from 0xa45f -read 0x69 from 0xa460 -read 0x73 from 0xa461 -read 0x69 from 0xa462 -read 0x6f from 0xa463 -read 0x6e from 0xa464 -read 0x0 from 0xa465 -read 0x66 from 0xa5a8 -read 0xa4 from 0xa5a9 -read 0xa0 from 0xa466 -read 0xa0 from 0xa466 -read 0x10 from 0xa467 -read 0x4 from 0xa468 -read 0x40 from 0xa469 -read 0x0 from 0xa46a -read 0x0 from 0xa46b -read 0x0 from 0xa46c -read 0x0 from 0xa46d -read 0x0 from 0xa46e -read 0x0 from 0xa46f -read 0x0 from 0xa470 -read 0x0 from 0xa471 -read 0x0 from 0xa472 -read 0x0 from 0xa473 -read 0x4e from 0xa474 -read 0x6f from 0xa475 -read 0x6e from 0xa476 -read 0x65 from 0xa477 -read 0x0 from 0xa478 -read 0x4e from 0xa479 -read 0x56 from 0xa47a -read 0x42 from 0xa47b -read 0x61 from 0xa47c -read 0x75 from 0xa47d -read 0x64 from 0xa47e -read 0x52 from 0xa47f -read 0x61 from 0xa480 -read 0x74 from 0xa481 -read 0x65 from 0xa482 -read 0x0 from 0xa483 -read 0x84 from 0xa5aa -read 0xa4 from 0xa5ab -read 0xa0 from 0xa484 -read 0xa0 from 0xa484 -read 0x20 from 0xa485 -read 0x4 from 0xa486 -read 0x0 from 0xa487 -read 0x0 from 0xa488 -read 0x0 from 0xa489 -read 0x0 from 0xa48a -read 0x0 from 0xa48b -read 0x0 from 0xa48c -read 0x0 from 0xa48d -read 0x0 from 0xa48e -read 0x0 from 0xa48f -read 0x78 from 0xa490 -read 0x0 from 0xa491 -read 0x4e from 0xa492 -read 0x6f from 0xa493 -read 0x6e from 0xa494 -read 0x65 from 0xa495 -read 0x0 from 0xa496 -read 0x4e from 0xa497 -read 0x56 from 0xa498 -read 0x55 from 0xa499 -read 0x6e from 0xa49a -read 0x69 from 0xa49b -read 0x74 from 0xa49c -read 0x4e from 0xa49d -read 0x75 from 0xa49e -read 0x6d from 0xa49f -read 0x62 from 0xa4a0 -read 0x65 from 0xa4a1 -read 0x72 from 0xa4a2 -read 0x0 from 0xa4a3 -read 0xa4 from 0xa5ac -read 0xa4 from 0xa5ad -read 0xa0 from 0xa4a4 -read 0xa0 from 0xa4a4 -read 0x10 from 0xa4a5 -read 0x4 from 0xa4a6 -read 0x0 from 0xa4a7 -read 0x0 from 0xa4a8 -read 0x0 from 0xa4a9 -read 0x0 from 0xa4aa -read 0x0 from 0xa4ab -read 0x0 from 0xa4ac -read 0x0 from 0xa4ad -read 0x0 from 0xa4ae -read 0x0 from 0xa4af -read 0x38 from 0xa4b0 -read 0x0 from 0xa4b1 -read 0x4e from 0xa4b2 -read 0x6f from 0xa4b3 -read 0x6e from 0xa4b4 -read 0x65 from 0xa4b5 -read 0x0 from 0xa4b6 -read 0x4e from 0xa4b7 -read 0x56 from 0xa4b8 -read 0x57 from 0xa4b9 -read 0x61 from 0xa4ba -read 0x74 from 0xa4bb -read 0x63 from 0xa4bc -read 0x68 from 0xa4bd -read 0x44 from 0xa4be -read 0x6f from 0xa4bf -read 0x67 from 0xa4c0 -read 0x54 from 0xa4c1 -read 0x69 from 0xa4c2 -read 0x6d from 0xa4c3 -read 0x65 from 0xa4c4 -read 0x6f from 0xa4c5 -read 0x75 from 0xa4c6 -read 0x74 from 0xa4c7 -read 0x0 from 0xa4c8 -read 0xca from 0xa5ae -read 0xa4 from 0xa5af -read 0xa0 from 0xa4ca -read 0xa0 from 0xa4ca -read 0x10 from 0xa4cb -read 0x2 from 0xa4cc -read 0x0 from 0xa4cd -read 0x0 from 0xa4ce -read 0x0 from 0xa4cf -read 0x0 from 0xa4d0 -read 0x0 from 0xa4d1 -read 0x0 from 0xa4d2 -read 0x0 from 0xa4d3 -read 0x0 from 0xa4d4 -read 0x0 from 0xa4d5 -read 0x98 from 0xa4d6 -read 0x9 from 0xa4d7 -read 0x4e from 0xa4d8 -read 0x6f from 0xa4d9 -read 0x6e from 0xa4da -read 0x65 from 0xa4db -read 0x0 from 0xa4dc -read 0x45 from 0xa4dd -read 0x6e from 0xa4de -read 0x63 from 0xa4df -read 0x4d from 0xa4e0 -read 0x6f from 0xa4e1 -read 0x64 from 0xa4e2 -read 0x65 from 0xa4e3 -read 0x30 from 0xa4e4 -read 0x0 from 0xa4e5 -read 0xe6 from 0xa5b0 -read 0xa4 from 0xa5b1 -read 0xa0 from 0xa4e6 -read 0xa0 from 0xa4e6 -read 0x10 from 0xa4e7 -read 0x2 from 0xa4e8 -read 0x0 from 0xa4e9 -read 0x0 from 0xa4ea -read 0x0 from 0xa4eb -read 0x0 from 0xa4ec -read 0x0 from 0xa4ed -read 0x0 from 0xa4ee -read 0x0 from 0xa4ef -read 0x0 from 0xa4f0 -read 0x0 from 0xa4f1 -read 0x9a from 0xa4f2 -read 0x9 from 0xa4f3 -read 0x4e from 0xa4f4 -read 0x6f from 0xa4f5 -read 0x6e from 0xa4f6 -read 0x65 from 0xa4f7 -read 0x0 from 0xa4f8 -read 0x45 from 0xa4f9 -read 0x6e from 0xa4fa -read 0x63 from 0xa4fb -read 0x4d from 0xa4fc -read 0x6f from 0xa4fd -read 0x64 from 0xa4fe -read 0x65 from 0xa4ff -read 0x31 from 0xa500 -read 0x0 from 0xa501 -read 0x2 from 0xa5b2 -read 0xa5 from 0xa5b3 -read 0xa0 from 0xa502 -read 0xa0 from 0xa502 -read 0x10 from 0xa503 -read 0x4 from 0xa504 -read 0x0 from 0xa505 -read 0x0 from 0xa506 -read 0x0 from 0xa507 -read 0x0 from 0xa508 -read 0x0 from 0xa509 -read 0x0 from 0xa50a -read 0x0 from 0xa50b -read 0x0 from 0xa50c -read 0x0 from 0xa50d -read 0x3a from 0xa50e -read 0x0 from 0xa50f -read 0x4e from 0xa510 -read 0x6f from 0xa511 -read 0x6e from 0xa512 -read 0x65 from 0xa513 -read 0x0 from 0xa514 -read 0x4e from 0xa515 -read 0x56 from 0xa516 -read 0x45 from 0xa517 -read 0x6e from 0xa518 -read 0x63 from 0xa519 -read 0x4d from 0xa51a -read 0x6f from 0xa51b -read 0x64 from 0xa51c -read 0x65 from 0xa51d -read 0x30 from 0xa51e -read 0x0 from 0xa51f -read 0x20 from 0xa5b4 -read 0xa5 from 0xa5b5 -read 0xa0 from 0xa520 -read 0xa0 from 0xa520 -read 0x10 from 0xa521 -read 0x4 from 0xa522 -read 0x0 from 0xa523 -read 0x0 from 0xa524 -read 0x0 from 0xa525 -read 0x0 from 0xa526 -read 0x0 from 0xa527 -read 0x0 from 0xa528 -read 0x0 from 0xa529 -read 0x0 from 0xa52a -read 0x0 from 0xa52b -read 0x3c from 0xa52c -read 0x0 from 0xa52d -read 0x4e from 0xa52e -read 0x6f from 0xa52f -read 0x6e from 0xa530 -read 0x65 from 0xa531 -read 0x0 from 0xa532 -read 0x4e from 0xa533 -read 0x56 from 0xa534 -read 0x45 from 0xa535 -read 0x6e from 0xa536 -read 0x63 from 0xa537 -read 0x4d from 0xa538 -read 0x6f from 0xa539 -read 0x64 from 0xa53a -read 0x65 from 0xa53b -read 0x31 from 0xa53c -read 0x0 from 0xa53d -read 0x0 from 0xa5b6 -read 0x0 from 0xa5b7 -read 0xe from 0x95c -read 0x0 from 0x95d -Set Reserved stuff -read 0x9 0x0 from 0x0 -Set Reserved stuff -Set Reserved stuff -read 0x76 0x1 0x0 0x10 from 0x78 -Set Reserved stuff -Set Reserved stuff -read 0x32 0x0 from 0x38 -Set Reserved stuff -Set Reserved stuff -read 0x0 0x0 from 0x3a -Set Reserved stuff -Set Reserved stuff -read 0x0 0x0 from 0x3c -Set Reserved stuff -read 0x90 from 0xa53e -read 0xa2 from 0xa53f -read 0xb0 from 0xa290 -read 0xb0 from 0xa290 -read 0x0 from 0xa291 -read 0x0 from 0xa292 -read 0x0 from 0xa293 -read 0x53 from 0xa294 -read 0x74 from 0xa295 -read 0x61 from 0xa296 -read 0x6e from 0xa297 -read 0x64 from 0xa298 -read 0x61 from 0xa299 -read 0x72 from 0xa29a -read 0x64 from 0xa29b -read 0x0 from 0xa29c -read 0x9e from 0xa540 -read 0xa2 from 0xa541 -read 0xb0 from 0xa29e -read 0xb0 from 0xa29e -read 0x0 from 0xa29f -read 0x1 from 0xa2a0 -read 0x0 from 0xa2a1 -read 0x49 from 0xa2a2 -read 0x4f from 0xa2a3 -read 0x5f from 0xa2a4 -read 0x53 from 0xa2a5 -read 0x70 from 0xa2a6 -read 0x69 from 0xa2a7 -read 0x6e from 0xa2a8 -read 0x0 from 0xa2a9 -read 0xd2 from 0xa542 -read 0xa2 from 0xa543 -read 0xa0 from 0xa2d2 -read 0xa0 from 0xa2d2 -read 0x20 from 0xa2d3 -read 0x1 from 0xa2d4 -read 0x0 from 0xa2d5 -read 0x0 from 0xa2d6 -read 0x0 from 0xa2d7 -read 0x0 from 0xa2d8 -read 0x0 from 0xa2d9 -read 0x0 from 0xa2da -read 0x0 from 0xa2db -read 0x0 from 0xa2dc -read 0x0 from 0xa2dd -read 0x8 from 0xa2de -read 0x8 from 0xa2df -read 0x4e from 0xa2e0 -read 0x6f from 0xa2e1 -read 0x6e from 0xa2e2 -read 0x65 from 0xa2e3 -read 0x0 from 0xa2e4 -read 0x49 from 0xa2e5 -read 0x6e from 0xa2e6 -read 0x70 from 0xa2e7 -read 0x75 from 0xa2e8 -read 0x74 from 0xa2e9 -read 0x0 from 0xa2ea -read 0xec from 0xa544 -read 0xa2 from 0xa545 -read 0xa0 from 0xa2ec -read 0xa0 from 0xa2ec -read 0x10 from 0xa2ed -read 0x1 from 0xa2ee -read 0x80 from 0xa2ef -read 0x0 from 0xa2f0 -read 0x0 from 0xa2f1 -read 0x0 from 0xa2f2 -read 0x0 from 0xa2f3 -read 0x0 from 0xa2f4 -read 0x0 from 0xa2f5 -read 0x0 from 0xa2f6 -read 0x0 from 0xa2f7 -read 0x0 from 0xa2f8 -read 0x8 from 0xa2f9 -read 0x4e from 0xa2fa -read 0x6f from 0xa2fb -read 0x6e from 0xa2fc -read 0x65 from 0xa2fd -read 0x0 from 0xa2fe -read 0x4f from 0xa2ff -read 0x75 from 0xa300 -read 0x74 from 0xa301 -read 0x70 from 0xa302 -read 0x75 from 0xa303 -read 0x74 from 0xa304 -read 0x0 from 0xa305 -read 0x6 from 0xa546 -read 0xa3 from 0xa547 -read 0xa0 from 0xa306 -read 0xa0 from 0xa306 -read 0x10 from 0xa307 -read 0x2 from 0xa308 -read 0x80 from 0xa309 -read 0x0 from 0xa30a -read 0x0 from 0xa30b -read 0x0 from 0xa30c -read 0x0 from 0xa30d -read 0x0 from 0xa30e -read 0x0 from 0xa30f -read 0xc8 from 0xa310 -read 0x42 from 0xa311 -read 0x40 from 0xa312 -read 0x8 from 0xa313 -read 0x50 from 0xa314 -read 0x65 from 0xa315 -read 0x72 from 0xa316 -read 0x63 from 0xa317 -read 0x65 from 0xa318 -read 0x6e from 0xa319 -read 0x74 from 0xa31a -read 0x0 from 0xa31b -read 0x53 from 0xa31c -read 0x70 from 0xa31d -read 0x69 from 0xa31e -read 0x6e from 0xa31f -read 0x4f from 0xa320 -read 0x75 from 0xa321 -read 0x74 from 0xa322 -read 0x0 from 0xa323 -read 0x24 from 0xa548 -read 0xa3 from 0xa549 -read 0xa0 from 0xa324 -read 0xa0 from 0xa324 -read 0x8 from 0xa325 -read 0x7 from 0xa326 -read 0x80 from 0xa327 -read 0x0 from 0xa328 -read 0x0 from 0xa329 -read 0x0 from 0xa32a -read 0x0 from 0xa32b -read 0x0 from 0xa32c -read 0x0 from 0xa32d -read 0x0 from 0xa32e -read 0x0 from 0xa32f -read 0x42 from 0xa330 -read 0x8 from 0xa331 -read 0x4e from 0xa332 -read 0x6f from 0xa333 -read 0x6e from 0xa334 -read 0x65 from 0xa335 -read 0x0 from 0xa336 -read 0x53 from 0xa337 -read 0x70 from 0xa338 -read 0x69 from 0xa339 -read 0x6e from 0xa33a -read 0x45 from 0xa33b -read 0x6e from 0xa33c -read 0x61 from 0xa33d -read 0x0 from 0xa33e -read 0x40 from 0xa54a -read 0xa3 from 0xa54b -read 0xa0 from 0xa340 -read 0xa0 from 0xa340 -read 0x8 from 0xa341 -read 0x7 from 0xa342 -read 0x80 from 0xa343 -read 0x0 from 0xa344 -read 0x0 from 0xa345 -read 0x0 from 0xa346 -read 0x0 from 0xa347 -read 0x0 from 0xa348 -read 0x0 from 0xa349 -read 0x0 from 0xa34a -read 0x0 from 0xa34b -read 0x43 from 0xa34c -read 0x8 from 0xa34d -read 0x4e from 0xa34e -read 0x6f from 0xa34f -read 0x6e from 0xa350 -read 0x65 from 0xa351 -read 0x0 from 0xa352 -read 0x53 from 0xa353 -read 0x70 from 0xa354 -read 0x69 from 0xa355 -read 0x6e from 0xa356 -read 0x44 from 0xa357 -read 0x69 from 0xa358 -read 0x72 from 0xa359 -read 0x0 from 0xa35a -read 0x0 from 0xa54c -read 0x0 from 0xa54d -Get LBP cookie -Set Command timeout -Set LBPstatus -Get LBP status -UnitNumberRPC -Get card name char0 -Get card name char1 -Get card name char2 -Get card name char3 -Set Reserved stuff -DiscoveryRPC -ProcessDataRPC -Set Reserved stuff -Get undefined stuff -Get undefined stuff -Get config name char3 -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -Set Reserved stuff -Get LBP cookie -Set Command timeout -Set LBPstatus -Get LBP status -UnitNumberRPC -Get card name char0 -Get card name char1 -Get card name char2 -Get card name char3 -Set Reserved stuff -DiscoveryRPC -ProcessDataRPC -Set Reserved stuff -Get undefined stuff -Get undefined stuff -Get undefined stuff -Get undefined stuff -Get config name char3 -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC -ProcessDataRPC diff --git a/memtemp/memtemp.c b/memtemp/memtemp.c deleted file mode 100644 index 4bbdf225..00000000 --- a/memtemp/memtemp.c +++ /dev/null @@ -1,464 +0,0 @@ - -#include -#include -#include - -#define MEM_SIZE 1024 - -//process data -#define RECORD_TYPE_PROCESS_DATA_RECORD 0xA0 -#define DATA_TYPE_PAD 0x00 -#define DATA_TYPE_BITS 0x01 -#define DATA_TYPE_UNSIGNED 0x02 -#define DATA_TYPE_SIGNED 0x03 -#define DATA_TYPE_NONVOL_UNSIGNED 0x04 -#define DATA_TYPE_NONVOL_SIGNED 0x05 -#define DATA_TYPE_NONVOL_STREAM 0x06 -#define DATA_TYPE_NONVOL_BOOLEAN 0x07 - -#define DATA_DIRECTION_INPUT 0x00 -#define DATA_DIRECTION_BI_DIRECTIONAL 0x40 -#define DATA_DIRECTION_OUTPUT 0x80 - -//modes -#define RECORD_TYPE_MODE_DATA_RECORD 0xB0 - -#define NO_MODES 2//gtoc modes -#define NO_GPD 1//gtoc process data -#define NO_PD 4//process data - -#define IS_INPUT(pdr) (pdr->data_direction != 0x80) -#define IS_OUTPUT(pdr) (pdr->data_direction != 0x00) - -#define MAX_PD_STRLEN 32 // this is the max space for both the unit and name strings in the PD descriptors -#define MAX_PD_VAL_BYTES 64 // this should be >= the sum of the data sizes of all pd vars - -#define MEMPTR(p) ((uint32_t)&p-(uint32_t)&memory) - -#define MEMU8(ptr) (memory.bytes[ptr]) -#define MEMU16(ptr) (memory.bytes[ptr] | memory.bytes[ptr+1]<<8) -#define MEMU32(ptr) (memory.bytes[ptr] | memory.bytes[ptr+1]<<8 | memory.bytes[ptr+2]<<16 | memory.bytes[ptr+3]<<24) - -#define NUM_BYTES(bits) (bits / 8 + (bits % 8 > 0 ? 1 : 0)) - -#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) - -#define SIGNED(pd) (pd->data_type == DATA_TYPE_SIGNED || pd->data_type == DATA_TYPE_NONVOL_SIGNED) -#define UNSIGNED(pd) (pd->data_type == DATA_TYPE_UNSIGNED || pd->data_type == DATA_TYPE_NONVOL_UNSIGNED) - - -typedef struct{ - uint8_t record_type;//0xa0 - uint8_t data_size; - uint8_t data_type; - uint8_t data_direction; - float param_min; - float param_max; - uint16_t data_addr; - char names; // we can pick up the address of that member for a memory location to write strings to. -} process_data_descriptor_t; - -typedef struct{ - uint8_t record_type;//0xb0 - uint8_t index; - uint8_t type; - uint8_t unused; - char names; -} mode_descriptor_t; - - - -typedef struct{ - uint8_t input; // these are in BITS now. I'll convert to bytes when I respond to the rpc. - uint8_t output; - uint16_t ptocp;//pointer to process data table - uint16_t gtocp;//pointer to mode data table -} discovery_rpc_t; - - -typedef union { - struct { - discovery_rpc_t discovery; - uint8_t heap[MEM_SIZE - sizeof(discovery_rpc_t)]; - }; - - uint8_t bytes[MEM_SIZE]; -} memory_t; - -typedef struct { - process_data_descriptor_t *ptr; - float range; - uint32_t bitmax; -} pd_metadata_t; - - -static memory_t memory; -static uint8_t *heap_ptr; - -process_data_descriptor_t create_pdr(uint8_t data_size_in_bits, uint8_t data_type, uint8_t data_dir, float param_min, float param_max) { - process_data_descriptor_t pd; - - pd.record_type = RECORD_TYPE_PROCESS_DATA_RECORD; - pd.data_size = data_size_in_bits; - pd.data_type = data_type; - pd.data_direction = data_dir; - pd.param_min = param_min; - pd.param_max = param_max; -// strcpy(pd.names, unit_string); -// strcpy(pd.names + strlen(unit_string) + 1, name_string); - - return pd; -} - -mode_descriptor_t create_mdr(uint8_t index, uint8_t type) { - mode_descriptor_t md; - - md.record_type = RECORD_TYPE_MODE_DATA_RECORD; - md.index = index; - md.type = type; - md.unused = 0x00; - //strcpy(md.name_string, name_string); - - return md; -} - -#define BITSLEFT(ptr) (8-ptr) - -void process_data_rpc(uint8_t *input, uint8_t *output) { - - uint16_t *ptocp = (uint16_t *)(memory.bytes + memory.discovery.ptocp); - - *(input++) = 0x00; // fault byte, just for easy recognition - *input = 0x00; // clear the next byte - - // data needs to be packed and unpacked based on its type and size - // input is a pointer to the data that gets sent back to the host - // need a bit pointer to keep track of partials - - uint8_t output_bit_ptr = 0; - uint8_t input_bit_ptr = 0; - - while(*ptocp != 0x0000) { - process_data_descriptor_t *pd = (process_data_descriptor_t *)(memory.bytes + *ptocp++); - - if (IS_INPUT(pd)) { - //printf("input pd data size is %d\n", pd->data_size); - uint16_t data_addr = pd->data_addr; - uint8_t data_size = pd->data_size; - uint8_t data_bit_ptr = 0; - - //*(input++) = MEMU8(pd->data_addr); - while(data_size > 0) { - uint8_t bits_to_pack = data_size < BITSLEFT(input_bit_ptr) ? data_size : BITSLEFT(input_bit_ptr); - if (BITSLEFT(data_bit_ptr) < bits_to_pack) { bits_to_pack = BITSLEFT(data_bit_ptr); } - - //printf("encoding partial byte, need to read %d bits from the data_val 0x%02x at bit position %d\n", bits_to_pack, MEMU8(data_addr), data_bit_ptr); - - uint8_t mask = ((1<> data_bit_ptr) << input_bit_ptr; - - //printf("*input is 0x%02x\n", *input); - input_bit_ptr += bits_to_pack; - data_bit_ptr += bits_to_pack; - data_size -= bits_to_pack; - if((input_bit_ptr %= 8) == 0) *++input = 0x00; // clear the next byte - if((data_bit_ptr %= 8) == 0) data_addr++; - } - } - if (IS_OUTPUT(pd)) { - // printf("output pd data size is %d\n", pd->data_size); - uint16_t data_addr = pd->data_addr; - uint8_t data_size = pd->data_size; - - uint8_t val_bits_remaining = 8; - uint8_t val = 0x00; - - while(data_size > 0) { - // the number of bits to unpack this iteration is the number of bits remaining in the pd, or the number of bits remaining in the output byte, - // whichever is smaller. Then, it can be even smaller if we have less room in the current val. - - uint8_t bits_to_unpack = data_size < BITSLEFT(output_bit_ptr) ? data_size : BITSLEFT(output_bit_ptr); - if (val_bits_remaining < bits_to_unpack) { bits_to_unpack = val_bits_remaining; } - - // printf("decoding partial byte, need to read %d bits from current output byte 0x%02x at bit position %d\n", bits_to_unpack, *output, output_bit_ptr); - - // create a bitmask the width of the bits to read, shifted to the position in the output byte that we're pointing to - uint8_t mask = ((1<> (output_bit_ptr)) << (8-val_bits_remaining); - - // printf("val is 0x%02x\n", val); - - val_bits_remaining -= bits_to_unpack; - data_size -= bits_to_unpack; - output_bit_ptr += bits_to_unpack; - - if((output_bit_ptr %= 8) == 0) output++; - - if(val_bits_remaining == 0 || data_size == 0) { - MEMU8(data_addr++) = val; - // printf("adding 0x%02x to data\n", val); - val_bits_remaining = 8; - val = 0x00; - } - } - // now we've finished unpacking it and storing it in memory, but we have to fix up the high bits if it wasn't a byte-aligned datasize. - // for instance, if we receive 0xFFF in a 12 bit field, that is a negative number, but we stored it as 0x0FFF in memory. - // strategy is to set the most significant n bits of the MSB to the most significant bit of the output value, iff the pd is defined as signed. - if (SIGNED(pd) && pd->data_size % 8 != 0) { - uint8_t msb_addr = pd->data_addr + NUM_BYTES(pd->data_size) - 1; - //printf("in output fixup. MSB: 0x%02x\n", MEMU8(msb_addr)); - if(MEMU8(msb_addr) & 1<<(pd->data_size%8 - 1)) { - uint8_t mask = 0xFF ^ ((1<data_size%8) - 1); - //printf("applying mask: 0x%02x\n", mask); - MEMU8(msb_addr) |= mask; - } - - //printf("fixed up val: 0x%02x\n", MEMU8(msb_addr)); - } - } - } -} - - -void dump_memory_range(uint16_t start, uint16_t end) { - start -= (start % 16); - end -= ((end+1) % 16); - printf("dump memory from 0x%04x to 0x%04x\n\n", start, end); - - printf(" "); - for(int i = 0; i < 16; i++) { - printf(" %x ", i); - } - - printf("\n---------------------------------------------------\n"); - - for(int j = start >> 4; j <= end >> 4; j++) { - printf("%03x ", j); - for (int i = 0; i < 16; i++) { - uint16_t addr = (j<<4) | i; - printf("%02x ", memory.bytes[addr]); - } - printf("\n"); - } - printf("\n"); -} - -void dump_memory() { - dump_memory_range(0, MEM_SIZE); -} - -void write_memory_to_file() { - FILE *fileptr; - uint8_t *buffer; - long filelen; - - fileptr = fopen("test.hex", "wb"); - - fwrite(memory.bytes, sizeof(uint8_t), MEM_SIZE, fileptr); - fclose(fileptr); - printf("Wrote memory out to test.hex\n"); -} - -uint16_t add_pd(char *name_string, char *unit_string, uint8_t data_size_in_bits, uint8_t data_type, uint8_t data_dir, float param_min, float param_max) { - process_data_descriptor_t pdr = create_pdr(data_size_in_bits, data_type, data_dir, param_min, param_max); - - pdr.data_addr = MEMPTR(*heap_ptr); - heap_ptr += NUM_BYTES(data_size_in_bits); - - memcpy(heap_ptr, &pdr, sizeof(process_data_descriptor_t)); - // note that we don't store the names in the struct anymore. The fixed-length struct is copied into memory, and then the nmaes go in directly behind it, so they'll read out properly - - uint16_t pd_ptr = MEMPTR(*heap_ptr); // save off the ptr to return, before we modify the heap ptr - - heap_ptr = (uint8_t *)&(((process_data_descriptor_t *)heap_ptr)->names); - - // copy the strings in after the pd - strcpy((char *)heap_ptr, unit_string); - heap_ptr += strlen(unit_string)+1; - strcpy((char *)heap_ptr, name_string); - heap_ptr += strlen(name_string)+1; - - return pd_ptr; -} - -uint16_t add_mode(char *name_string, uint8_t index, uint8_t type) { - mode_descriptor_t mdr = create_mdr(index, type); - - memcpy(heap_ptr, &mdr, sizeof(mode_descriptor_t)); - - uint16_t md_ptr = MEMPTR(*heap_ptr); - - heap_ptr = (uint8_t *)&(((mode_descriptor_t *)heap_ptr)->names); - - strcpy((char *)heap_ptr, name_string); - heap_ptr += strlen(name_string)+1; - - return md_ptr; -} - -void metadata(pd_metadata_t *pdm, process_data_descriptor_t *ptr) { - pdm->ptr = ptr; - pdm->range = ptr->data_type == DATA_TYPE_SIGNED ? MAX(ptr->param_min, ptr->param_max)*2 : ptr->param_max; - pdm->bitmax = (1<data_size)-1; -} - - -#define INDIRECT_PD(pd_ptr) ((process_data_descriptor_t *)(memory.bytes + *pd_ptr)) -#define DATA_DIR(pd_ptr) INDIRECT_PD(pd_ptr)->data_direction -#define DATA_SIZE(pd_ptr) INDIRECT_PD(pd_ptr)->data_size - -#define ADD_PROCESS_VAR(args) *ptocp = add_pd args; input_bits += IS_INPUT(INDIRECT_PD(ptocp)) ? DATA_SIZE(ptocp) : 0; output_bits += IS_OUTPUT(INDIRECT_PD(ptocp)) ? DATA_SIZE(ptocp) : 0; last_pd = INDIRECT_PD(ptocp++) -#define ADD_GLOBAL_VAR(args) *gtocp++ = add_pd args -#define ADD_MODE(args) *gtocp++ = add_mode args - -//#define SCALE_OUT(pd, val) (((float)val / (float)((1<data_size)-1) * (pd->param_max - pd->param_min)) + pd->param_min) -//#define SCALE_IN(pd, val) ((val - pd->param_min)/(pd->param_max - pd->param_min) * ((1<data_size)-1)) -//#define SCALE_IN(pd, val) (val * (pd->param_max - pd->param_min) / ((1<data_size)-1) + pd->param_min) - - - -float scale_out(pd_metadata_t pd, int32_t val) { - return val * pd.range / (float)pd.bitmax; -} - -int32_t scale_in(pd_metadata_t pd, float val) { - return CLAMP(val, pd.ptr->param_min, pd.ptr->param_max) * pd.bitmax / pd.range; -} - -int main(void) { - - heap_ptr = memory.heap; - - uint16_t input_bits = 8; // this starts at 8 bits = 1 byte for the fault byte - uint16_t output_bits = 0; - - // these are temp toc arrays that the macros will write pointers into. the tocs get copied to main memory after everything else is written in - uint16_t ptoc[32]; - uint16_t gtoc[32]; - - uint16_t *ptocp = ptoc; uint16_t *gtocp = gtoc; - process_data_descriptor_t *last_pd; - - pd_metadata_t cmd_vel; - - pd_metadata_t fb_vel; - - printf("sizeof pdr: %ld\n", sizeof(process_data_descriptor_t)); - - - ADD_PROCESS_VAR(("output_pins", "none", 4, DATA_TYPE_BITS, DATA_DIRECTION_OUTPUT, 0, 1)); - ADD_PROCESS_VAR(("cmd_vel", "rps", 12, DATA_TYPE_SIGNED, DATA_DIRECTION_OUTPUT, -1.0, 1.0)); metadata(&cmd_vel, last_pd); - ADD_PROCESS_VAR(("input_pins", "none", 4, DATA_TYPE_BITS, DATA_DIRECTION_INPUT, 0, 1)); - ADD_PROCESS_VAR(("fb_vel", "rps", 12, DATA_TYPE_SIGNED, DATA_DIRECTION_INPUT, -1.0, 1.0)); metadata(&fb_vel, last_pd); - - - printf("cmd_vel->data_addr: 0x%04x\n", cmd_vel.ptr->data_addr); - - ADD_GLOBAL_VAR(("swr", "non", 8, DATA_TYPE_UNSIGNED, DATA_DIRECTION_OUTPUT, 0, 0)); - - ADD_MODE(("foo", 0, 0)); - ADD_MODE(("io_", 1, 1)); - - - printf("input bits %d output bits %d\n", input_bits, output_bits); - if (input_bits % 8) ADD_PROCESS_VAR(("", "", 8 - (input_bits%8), DATA_TYPE_PAD, DATA_DIRECTION_INPUT, 0, 0)); - if (output_bits % 8) ADD_PROCESS_VAR(("", "", 8 - (output_bits%8), DATA_TYPE_PAD, DATA_DIRECTION_OUTPUT, 0, 0)); - - // todo: automatically create padding pds based on the mod remainder of input/output bits - - // now that all the toc entries have been added, write out the tocs to memory and set up the toc pointers - - memory.discovery.input = input_bits >> 3; - memory.discovery.output = output_bits >> 3; - - memory.discovery.ptocp = MEMPTR(*heap_ptr); - - for(uint8_t i = 0; i < ptocp - ptoc; i++) { - *heap_ptr++ = ptoc[i] & 0x00FF; - *heap_ptr++ = (ptoc[i] & 0xFF00) >> 8; - } - *heap_ptr++ = 0x00; *heap_ptr++ = 0x00; // this is the ptoc end marker - - memory.discovery.gtocp = MEMPTR(*heap_ptr); - - for(uint8_t i = 0; i < gtocp - gtoc; i++) { - *heap_ptr++ = gtoc[i] & 0x00FF; - *heap_ptr++ = (gtoc[i] & 0xFF00) >> 8; - } - *heap_ptr++ = 0x00; *heap_ptr++ = 0x00; // this is the gtoc end marker - - dump_memory_range(0, 0x100); - - - write_memory_to_file(); - - - printf("Scale out test: %f\n", scale_out(cmd_vel, (int16_t)0x7ff)); - printf("Scale out test: %f\n", scale_out(cmd_vel, (int16_t)0x3ff)); - printf("Scale out test: %f\n", scale_out(cmd_vel, (int16_t)0x1ff)); - printf("Scale out test: %f\n", scale_out(cmd_vel, (int16_t)0x000)); - printf("Scale out test: %f\n", scale_out(cmd_vel, (int16_t)0xe01)); - printf("Scale out test: %f\n", scale_out(cmd_vel, (int16_t)0xc01)); - printf("Scale out test: %f\n", scale_out(cmd_vel, (int16_t)0x801)); - - printf("Scale in test: 0x%04x (%d)\n", (int16_t)scale_in(fb_vel, 1), (int16_t)scale_in(fb_vel, 1)); - printf("Scale in test: 0x%04x (%d)\n", (int16_t)scale_in(fb_vel, 0.5), (int16_t)scale_in(fb_vel, 0.5)); - printf("Scale in test: 0x%04x (%d)\n", (int16_t)scale_in(fb_vel, 0.25), (int16_t)scale_in(fb_vel, 0.5)); - printf("Scale in test: 0x%04x (%d)\n", (int16_t)scale_in(fb_vel, 0), (int16_t)scale_in(fb_vel, 0)); - printf("Scale in test: 0x%04x (%d)\n", (int16_t)scale_in(fb_vel, -0.25), (int16_t)scale_in(fb_vel, 0.5)); - printf("Scale in test: 0x%04x (%d)\n", (int16_t)scale_in(fb_vel, -0.5), (int16_t)scale_in(fb_vel, -0.5)); - printf("Scale in test: 0x%04x (%d)\n", (int16_t)scale_in(fb_vel, -1), (int16_t)scale_in(fb_vel, -1)); - - - MEMU8(fb_vel.ptr->data_addr) = 0xFF; - MEMU8(fb_vel.ptr->data_addr + 1) = 0x07; - - uint8_t output_buf[memory.discovery.output]; - uint8_t input_buf[memory.discovery.input]; - - output_buf[0] = 0x1a; - output_buf[1] = 0xe0; - printf("incoming output bytes: "); for (uint8_t i = 0; i < memory.discovery.output; i++) { printf("0x%02x ", output_buf[i]); } printf("\n"); - process_data_rpc(input_buf, output_buf); - printf("outgoing input bytes: "); for (uint8_t i = 0; i < memory.discovery.input; i++) { printf("0x%02x ", input_buf[i]); } printf("\n"); - - - float cmd_vel_val = scale_out(cmd_vel, (int16_t)MEMU16(cmd_vel.ptr->data_addr)); - printf("cmd_vel's value is 0x%04x (%f)\n", MEMU16(cmd_vel.ptr->data_addr), cmd_vel_val); - - *((uint16_t *)&(memory.bytes[fb_vel.ptr->data_addr])) = scale_in(fb_vel, cmd_vel_val); - - printf("fb_vel's value is 0x%04x (%f)\n", MEMU16(fb_vel.ptr->data_addr), scale_out(fb_vel, (int16_t)MEMU16(fb_vel.ptr->data_addr))); - - - output_buf[0] = 0xfa; - output_buf[1] = 0x7f; - printf("incoming output bytes: "); for (uint8_t i = 0; i < memory.discovery.output; i++) { printf("0x%02x ", output_buf[i]); } printf("\n"); - process_data_rpc(input_buf, output_buf); - printf("outgoing input bytes: "); for (uint8_t i = 0; i < memory.discovery.input; i++) { printf("0x%02x ", input_buf[i]); } printf("\n"); - -/* - printf("setting fb and bidir\n"); - *fb_vel = 0xCA; - - output_buf[0] = 0x30; - output_buf[1] = 0x40; - - printf("updated vals: cmd_vel 0x%02x fb_vel 0x%02x bidir 0x%02x\n", *cmd_vel, *fb_vel, *bidir); - - printf("incoming output bytes: "); for (uint8_t i = 0; i < discovery_rpc.output; i++) { printf("0x%02x ", output_buf[i]); } printf("\n"); - process_data_rpc(input_buf, output_buf); - printf("outgoing input bytes: "); for (uint8_t i = 0; i < discovery_rpc.input; i++) { printf("0x%02x ", input_buf[i]); } printf("\n"); - - printf("updated vals: cmd_vel 0x%02x fb_vel 0x%02x bidir 0x%02x\n", *cmd_vel, *fb_vel, *bidir); - */ - - exit(0); -} \ No newline at end of file diff --git a/memtemp/sserial.sr b/memtemp/sserial.sr deleted file mode 100644 index 687d853225bf0f05f195341e8c54b83cb940ff2a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 84359 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

fhujNa?|y6cR&4$*$U%W`)0f!cYusZVN)s_ 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%0AbuzorD1EgNyNvVOZ>7l6!8 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 U{xE3CS_l3F4P&v|&EYoZ|6`Hut^fc4 diff --git a/memtemp/tocdump.c b/memtemp/tocdump.c deleted file mode 100644 index b0433b7e..00000000 --- a/memtemp/tocdump.c +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include -#include - -//#define MEMPTR(p) ((uint32_t)&p-(uint32_t)&memory) -#define RECORD_TYPE_PROCESS_DATA_RECORD 0xA0 -#define RECORD_TYPE_MODE_DATA_RECORD 0xB0 - -#define MEMU8(m, ptr) (m[ptr]) -#define MEMU16(m, ptr) (m[ptr] | m[ptr+1]<<8) -#define MEMU32(m, ptr) (m[ptr] | m[ptr+1]<<8 | m[ptr+2]<<16 | m[ptr+3]<<24) - -void print_tocs(uint8_t *m, uint16_t ptocp, uint16_t gtocp) { - uint16_t pd_ptr; - - printf("\nptoc: (at 0x%04x)\n", ptocp); - while(MEMU16(m, ptocp) != 0x0000) { - pd_ptr = MEMU16(m, ptocp); - printf("pd ptr: 0x%04x\n", pd_ptr); - - printf("\trectype: 0x%02x\n", MEMU8(m, pd_ptr++)); - printf("\tdatasize: 0x%02x\n", MEMU8(m, pd_ptr++)); - printf("\tdatatype: 0x%02x\n", MEMU8(m, pd_ptr++)); - printf("\tdatadir: 0x%02x\n", MEMU8(m, pd_ptr++)); - printf("\tparmmin: 0x%08x\n", MEMU32(m, pd_ptr)); pd_ptr += 4; - printf("\tparmmax: 0x%08x\n", MEMU32(m, pd_ptr)); pd_ptr += 4; - printf("\tdataaddr: 0x%04x\n", MEMU16(m, pd_ptr)); pd_ptr += 2; - char *unitstr = (char *)(m + pd_ptr); - printf("\tunitstr: %s\n", unitstr); - pd_ptr += strlen(unitstr) + 1; - char *namestr = (char *)(m + pd_ptr); - printf("\tnamestr: %s\n", namestr); - pd_ptr += strlen(namestr) + 1; - - ptocp += 2; - } - - printf("\ngtoc: (at 0x%04x)\n", gtocp); - while(MEMU16(m, gtocp) != 0x0000) { - pd_ptr = MEMU16(m, gtocp); - printf("pd ptr: 0x%04x\n", pd_ptr); - - uint8_t rectype = MEMU8(m, pd_ptr++); - printf("\trectype: 0x%02x\n", rectype); - switch(rectype) { - case RECORD_TYPE_PROCESS_DATA_RECORD: - printf("\tdatasize: 0x%02x\n", MEMU8(m, pd_ptr++)); - printf("\tdatatype: 0x%02x\n", MEMU8(m, pd_ptr++)); - printf("\tdatadir: 0x%02x\n", MEMU8(m, pd_ptr++)); - printf("\tparmmin: 0x%08x\n", MEMU32(m, pd_ptr)); pd_ptr += 4; - printf("\tparmmax: 0x%08x\n", MEMU32(m, pd_ptr)); pd_ptr += 4; - printf("\tdataaddr: 0x%04x\n", MEMU16(m, pd_ptr)); pd_ptr += 2; - char *unitstr = (char *)(m + pd_ptr); - printf("\tunitstr: %s\n", unitstr); - pd_ptr += strlen(unitstr) + 1; - char *namestr = (char *)(m + pd_ptr); - printf("\tnamestr: %s\n", namestr); - pd_ptr += strlen(namestr) + 1; - break; - case RECORD_TYPE_MODE_DATA_RECORD: - printf("\tindex: 0x%02x\n", pd_ptr++); - printf("\ttype: 0x%02x\n", pd_ptr++); - pd_ptr++; // skip 'unused' byte - namestr = (char *)(m + pd_ptr); - printf("\tnamestr: %s\n", namestr); - pd_ptr += strlen(namestr); - break; - } - - gtocp += 2; - } -} - -int main(void) { - - FILE *fileptr; - uint8_t *buffer; - long filelen; - - fileptr = fopen("test.hex", "rb"); // open in binary read mode - fseek(fileptr, 0, SEEK_END); // jump to the end of the file - filelen = ftell(fileptr); // get the byte offset of the end of the file - rewind(fileptr); // jump back to the beginning to start reading - - buffer = (uint8_t *)malloc((filelen)*sizeof(uint8_t)); - fread(buffer, filelen, 1, fileptr); - fclose(fileptr); - - printf("read mem.hex\n\n"); - - // MY memory dumps have the discovery_rpc struct at the beginning, so byte 0 and 1 are input and output byte counts, bytes 2/3 and 4/5 are the ptocp and gtocp. - uint16_t ptocp = buffer[2] | buffer[3]<<8; - uint16_t gtocp = buffer[4] | buffer[5]<<8; - print_tocs(buffer, ptocp, gtocp); -} \ No newline at end of file diff --git a/memtemp/tocdump.txt b/memtemp/tocdump.txt deleted file mode 100644 index 6cd7c893..00000000 --- a/memtemp/tocdump.txt +++ /dev/null @@ -1,306 +0,0 @@ -read mem.hex - - -ptoc: (at 0xa53e) -pd ptr: 0xa290 - rectype: 0xb0 - datasize: 0x00 - datatype: 0x00 - datadir: 0x00 - parmmin: 0x6e617453 - parmmax: 0x64726164 - dataaddr: 0x0000 - unitstr: ° - namestr:  -pd ptr: 0xa29e - rectype: 0xb0 - datasize: 0x00 - datatype: 0x01 - datadir: 0x00 - parmmin: 0x535f4f49 - parmmax: 0x006e6970 - dataaddr: 0x01b0 - unitstr:  - namestr: IO_Ana_Spin -pd ptr: 0xa2d2 - rectype: 0xa0 - datasize: 0x20 - datatype: 0x01 - datadir: 0x00 - parmmin: 0x00000000 - parmmax: 0x00000000 - dataaddr: 0x0808 - unitstr: None - namestr: Input -pd ptr: 0xa2ec - rectype: 0xa0 - datasize: 0x10 - datatype: 0x01 - datadir: 0x80 - parmmin: 0x00000000 - parmmax: 0x00000000 - dataaddr: 0x0800 - unitstr: None - namestr: Output -pd ptr: 0xa306 - rectype: 0xa0 - datasize: 0x10 - datatype: 0x02 - datadir: 0x80 - parmmin: 0x00000000 - parmmax: 0x42c80000 - dataaddr: 0x0840 - unitstr: Percent - namestr: SpinOut -pd ptr: 0xa324 - rectype: 0xa0 - datasize: 0x08 - datatype: 0x07 - datadir: 0x80 - parmmin: 0x00000000 - parmmax: 0x00000000 - dataaddr: 0x0842 - unitstr: None - namestr: SpinEna -pd ptr: 0xa340 - rectype: 0xa0 - datasize: 0x08 - datatype: 0x07 - datadir: 0x80 - parmmin: 0x00000000 - parmmax: 0x00000000 - dataaddr: 0x0843 - unitstr: None - namestr: SpinDir - -gtoc: (at 0xa584) -pd ptr: 0xa290 - rectype: 0xb0 - index: 0xa291 - type: 0xa292 - namestr: Standard -pd ptr: 0xa29e - rectype: 0xb0 - index: 0xa29f - type: 0xa2a0 - namestr: IO_Spin -pd ptr: 0xa2aa - rectype: 0xb0 - index: 0xa2ab - type: 0xa2ac - namestr: IO_Ana_Spin -pd ptr: 0xa2ba - rectype: 0xb0 - index: 0xa2bb - type: 0xa2bc - namestr: IO_Enc_Ana_Spin_FV -pd ptr: 0xa2d2 - rectype: 0xa0 - datasize: 0x20 - datatype: 0x01 - datadir: 0x00 - parmmin: 0x00000000 - parmmax: 0x00000000 - dataaddr: 0x0808 - unitstr: None - namestr: Input -pd ptr: 0xa2ec - rectype: 0xa0 - datasize: 0x10 - datatype: 0x01 - datadir: 0x80 - parmmin: 0x00000000 - parmmax: 0x00000000 - dataaddr: 0x0800 - unitstr: None - namestr: Output -pd ptr: 0xa306 - rectype: 0xa0 - datasize: 0x10 - datatype: 0x02 - datadir: 0x80 - parmmin: 0x00000000 - parmmax: 0x42c80000 - dataaddr: 0x0840 - unitstr: Percent - namestr: SpinOut -pd ptr: 0xa324 - rectype: 0xa0 - datasize: 0x08 - datatype: 0x07 - datadir: 0x80 - parmmin: 0x00000000 - parmmax: 0x00000000 - dataaddr: 0x0842 - unitstr: None - namestr: SpinEna -pd ptr: 0xa340 - rectype: 0xa0 - datasize: 0x08 - datatype: 0x07 - datadir: 0x80 - parmmin: 0x00000000 - parmmax: 0x00000000 - dataaddr: 0x0843 - unitstr: None - namestr: SpinDir -pd ptr: 0xa35c - rectype: 0xa0 - datasize: 0x08 - datatype: 0x02 - datadir: 0x00 - parmmin: 0x00000000 - parmmax: 0x42113333 - dataaddr: 0x0810 - unitstr: Volts - namestr: AnalogIn0 -pd ptr: 0xa37a - rectype: 0xa0 - datasize: 0x08 - datatype: 0x02 - datadir: 0x00 - parmmin: 0x00000000 - parmmax: 0x42113333 - dataaddr: 0x0811 - unitstr: Volts - namestr: AnalogIn1 -pd ptr: 0xa398 - rectype: 0xa0 - datasize: 0x08 - datatype: 0x02 - datadir: 0x00 - parmmin: 0x00000000 - parmmax: 0x42113333 - dataaddr: 0x0812 - unitstr: Volts - namestr: AnalogIn2 -pd ptr: 0xa3b6 - rectype: 0xa0 - datasize: 0x08 - datatype: 0x02 - datadir: 0x00 - parmmin: 0x00000000 - parmmax: 0x42113333 - dataaddr: 0x0813 - unitstr: Volts - namestr: AnalogIn3 -pd ptr: 0xa3d4 - rectype: 0xa0 - datasize: 0x10 - datatype: 0x02 - datadir: 0x00 - parmmin: 0x00000000 - parmmax: 0x42113333 - dataaddr: 0x0a18 - unitstr: Volts - namestr: FieldVoltage -pd ptr: 0xa3f6 - rectype: 0xa0 - datasize: 0x08 - datatype: 0x08 - datadir: 0x00 - parmmin: 0x00000000 - parmmax: 0x00000000 - dataaddr: 0x09a0 - unitstr: Counts - namestr: Enc0 -pd ptr: 0xa410 - rectype: 0xa0 - datasize: 0x08 - datatype: 0x08 - datadir: 0x00 - parmmin: 0x00000000 - parmmax: 0x00000000 - dataaddr: 0x09a2 - unitstr: Counts - namestr: Enc1 -pd ptr: 0xa42a - rectype: 0xa0 - datasize: 0x10 - datatype: 0x02 - datadir: 0x80 - parmmin: 0x00000000 - parmmax: 0x00000000 - dataaddr: 0x095c - unitstr: None - namestr: SwRevision -pd ptr: 0xa448 - rectype: 0xa0 - datasize: 0x10 - datatype: 0x02 - datadir: 0x80 - parmmin: 0x00000000 - parmmax: 0x00000000 - dataaddr: 0x0974 - unitstr: None - namestr: HwRevision -pd ptr: 0xa466 - rectype: 0xa0 - datasize: 0x10 - datatype: 0x04 - datadir: 0x40 - parmmin: 0x00000000 - parmmax: 0x00000000 - dataaddr: 0x0000 - unitstr: None - namestr: NVBaudRate -pd ptr: 0xa484 - rectype: 0xa0 - datasize: 0x20 - datatype: 0x04 - datadir: 0x00 - parmmin: 0x00000000 - parmmax: 0x00000000 - dataaddr: 0x0078 - unitstr: None - namestr: NVUnitNumber -pd ptr: 0xa4a4 - rectype: 0xa0 - datasize: 0x10 - datatype: 0x04 - datadir: 0x00 - parmmin: 0x00000000 - parmmax: 0x00000000 - dataaddr: 0x0038 - unitstr: None - namestr: NVWatchDogTimeout -pd ptr: 0xa4ca - rectype: 0xa0 - datasize: 0x10 - datatype: 0x02 - datadir: 0x00 - parmmin: 0x00000000 - parmmax: 0x00000000 - dataaddr: 0x0998 - unitstr: None - namestr: EncMode0 -pd ptr: 0xa4e6 - rectype: 0xa0 - datasize: 0x10 - datatype: 0x02 - datadir: 0x00 - parmmin: 0x00000000 - parmmax: 0x00000000 - dataaddr: 0x099a - unitstr: None - namestr: EncMode1 -pd ptr: 0xa502 - rectype: 0xa0 - datasize: 0x10 - datatype: 0x04 - datadir: 0x00 - parmmin: 0x00000000 - parmmax: 0x00000000 - dataaddr: 0x003a - unitstr: None - namestr: NVEncMode0 -pd ptr: 0xa520 - rectype: 0xa0 - datasize: 0x10 - datatype: 0x04 - datadir: 0x00 - parmmin: 0x00000000 - parmmax: 0x00000000 - dataaddr: 0x003c - unitstr: None - namestr: NVEncMode1 diff --git a/sim/gp b/sim/gp deleted file mode 100644 index ed28563a..00000000 --- a/sim/gp +++ /dev/null @@ -1,5 +0,0 @@ -set term x1 -set key autotitle columnheader -#set yrange [-3:400] -#set xrange [0.245:0.4] -plot "plot" every 1 using 1:2 w l, "plot" every 1 using 1:3 w l, "plot" every 1 using 1:4 w l, "plot" every 1 using 1:5 w l, "plot" every 1 using 1:6 w l, "plot" every 1 using 1:7 w l, "plot" every 1 using 1:8 w l, "plot" every 1 using 1:9 w l, "plot" every 1 using 1:10 w l diff --git a/sim/pwm.html b/sim/pwm.html deleted file mode 100644 index b66da0fc..00000000 --- a/sim/pwm.html +++ /dev/null @@ -1,403 +0,0 @@ - - -pwm - - - - - - - not supported - - - not supported -
- std
- SVM
- flat bottom SVM
- left pwm
- right pwm
- center pwm
- A
- B
- - - - diff --git a/sim/sim.cpp b/sim/sim.cpp deleted file mode 100644 index b07afd13..00000000 --- a/sim/sim.cpp +++ /dev/null @@ -1,410 +0,0 @@ -#include "sim.h" - -// Rcpp implementation of the 1D TVD algorithm in: -// Condat, L (2012) A Direct Algorithm for 1D Total Variation Denoising -// http://hal.inria.fr/docs/00/67/50/43/PDF/condat_killer_tv.pdf -// Accessed 11 August 2014. -// [[Rcpp::export]] -void tvd_1d_condat(std::vector &y, std::vector &x, int N, float lambda) -{ - int k, k0, kn, kp, i; - float vmin, vmax, umin, umax; - - k = k0 = kn = kp = 1; - vmin = y[0] - lambda; - vmax = y[0] + lambda; - umin = lambda; - umax = -lambda; - - while (1) - { - // b - if (k == N) - { - x[k-1] = vmin + umin; - break; - } - - if (y[k] + umin < vmin - lambda) - { - // b1 - for (i = k0-1; i < kn; i++) - x[i] = vmin; - kn++; - k = k0 = kp = kn; - vmin = y[k-1]; - vmax = y[k-1] + 2*lambda; - umin = lambda; - umax = -lambda; - } - else if (y[k] + umax > vmax + lambda) - { - // b2 - for (i = k0-1; i < kp; i++) - x[i] = vmax; - kp++; - k = k0 = kn = kp; - vmin = y[k-1] - 2*lambda; - vmax = y[k-1]; - umin = lambda; - umax = -lambda; - } - else - { - // b3 - k++; - umin = umin + y[k-1] - vmin; - umax = umax + y[k-1] - vmax; - if (umin >= lambda) - { - // b31 - vmin = vmin + (umin - lambda)/((float)(k - k0 + 1)); - umin = lambda; - kn = k; - } - if (umax <= -lambda) - { - // b32 - vmax = vmax + (umax + lambda)/((float)(k - k0 + 1)); - umax = -lambda; - kp = k; - } - } - - // c - if (k == N) - { - if (umin < 0) - { - // c1 - for (i = k0-1; i < kn; i++) - x[i] = vmin; - kn++; - k = k0 = kn; - vmin = y[k-1]; - umin = lambda; - umax = y[k-1] + lambda - vmax; - } - else if (umax > 0) - { - // c2 - for (i = k0-1; i < kn; i++) - x[i] = vmax; - kp++; - k = k0 = kp; - vmax = y[k-1]; - umax = -lambda; - umin = y[k-1] - lambda - vmin; - } - else - { - // c3 - for (i = k0-1; i < N; i++) - x[i] = vmin + umin/((float)(k - k0 + 1)); - break; - } - } - } -} - - -// Rcpp implementation of the 1D TVD algorithm in: -// Condat, L (2012) A Direct Algorithm for 1D Total Variation Denoising -// http://hal.inria.fr/docs/00/67/50/43/PDF/condat_killer_tv.pdf -// Accessed 11 August 2014. -// [[Rcpp::export]] -std::vector tvd_1d_condat_worker(std::vector& y, double lambda) -{ - // NOTE: in wrapping R code, verify that y.size() <= 2^32-1. Although - // newer versions of R get around this index limit, Rcpp is still - // limited to int indices. - int N = y.size(); - int k, k0, kn, kp, i; - double vmin, vmax, umin, umax; - std::vector x(N); - - k = k0 = kn = kp = 1; - vmin = y[0] - lambda; - vmax = y[0] + lambda; - umin = lambda; - umax = -lambda; - - while (true) - { - // b - if (k == N) - { - x[k-1] = vmin + umin; - break; - } - - if (y[k] + umin < vmin - lambda) - { - // b1 - for (i = k0-1; i < kn; i++) - x[i] = vmin; - kn++; - k = k0 = kp = kn; - vmin = y[k-1]; - vmax = y[k-1] + 2*lambda; - umin = lambda; - umax = -lambda; - } - else if (y[k] + umax > vmax + lambda) - { - // b2 - for (i = k0-1; i < kp; i++) - x[i] = vmax; - kp++; - k = k0 = kn = kp; - vmin = y[k-1] - 2*lambda; - vmax = y[k-1]; - umin = lambda; - umax = -lambda; - } - else - { - // b3 - k++; - umin = umin + y[k-1] - vmin; - umax = umax + y[k-1] - vmax; - if (umin >= lambda) - { - // b31 - vmin = vmin + (umin - lambda)/(static_cast(k - k0 + 1)); - umin = lambda; - kn = k; - } - if (umax <= -lambda) - { - // b32 - vmax = vmax + (umax + lambda)/(static_cast(k - k0 + 1)); - umax = -lambda; - kp = k; - } - } - - // c - if (k == N) - { - if (umin < 0) - { - // c1 - for (i = k0-1; i < kn; i++) - x[i] = vmin; - kn++; - k = k0 = kn; - vmin = y[k-1]; - umin = lambda; - umax = y[k-1] + lambda - vmax; - } - else if (umax > 0) - { - // c2 - for (i = k0-1; i < kn; i++) - x[i] = vmax; - kp++; - k = k0 = kp; - vmax = y[k-1]; - umax = -lambda; - umin = y[k-1] - lambda - vmin; - } - else - { - // c3 - for (i = k0-1; i < N; i++) - x[i] = vmin + umin/(static_cast(k - k0 + 1)); - break; - } - } - } - - return x; -} - -int main(){ - float sim_time = 0.0; - float sim_step = 0.0001; - float sim_end_time = 0.1; - - srand(14235); - - // e240 - mot_c mot; - mot.reset(); - mot.mech_spec.max_rps = 83.3; - mot.mech_spec.mot_type = mot_c::mech_spec_s::DC; - mot.mech_spec.pole_count = 1; - mot.mech_spec.friction = 0.021;//0.021; - mot.mech_spec.damping = 0.0000426;//0.0000426; - mot.mech_spec.inertia = 0.0000268;//0.0000268; - - mot.elec_spec.max_i = 13.9; - mot.elec_spec.i = 1.9; - mot.elec_spec.nm_a = 0.135; - mot.elec_spec.r = 5.4; - mot.elec_spec.l = 0.0082; - mot.elec_spec.v_rps = 0.852; - mot.elec_spec.slip = 0; - - mot.feedback.type = mot_c::feedback_s::RES; - mot.feedback.count = 1; - mot.feedback.res_offset = 0.0; - mot.noise.sin_scale = 1.0; - mot.noise.cos_scale = 1.0; - mot.noise.sin_offset = 0.0; - mot.noise.cos_offset = 0.0; - mot.noise.var = 0.0; - - mot.load.friction = 0.0; - mot.load.load = 0.0; - mot.load.damping = 0.0; - mot.load.inertia = 0.0; - - // bautz e728 - mot_c mot2; - mot2.reset(); - mot2.mech_spec.max_rps = 50; - mot2.mech_spec.mot_type = mot_c::mech_spec_s::DC; - mot2.mech_spec.pole_count = 1; - mot2.mech_spec.friction = 0.18; - mot2.mech_spec.damping = 0.004236; - mot2.mech_spec.inertia = 0.0012; - - mot2.elec_spec.max_i = 60; - mot2.elec_spec.i = 10; - mot2.elec_spec.nm_a = 0.36; - mot2.elec_spec.r = 0.67; - mot2.elec_spec.l = 0.0011; - mot2.elec_spec.v_rps = 2.28; - mot2.elec_spec.slip = 0; - - mot2.feedback.type = mot_c::feedback_s::RES; - mot2.feedback.count = 1; - mot2.feedback.res_offset = 0.0; - mot2.noise.sin_scale = 1.0; - mot2.noise.cos_scale = 1.0; - mot2.noise.sin_offset = 0.0; - mot2.noise.cos_offset = 0.0; - mot2.noise.var = 0.0; - - mot2.load.friction = 0.0; - mot2.load.load = 0.0; - mot2.load.damping = 0.0; - mot2.load.inertia = 0.0; - - // bosch - mot_c mot3; - mot3.reset(); - mot3.mech_spec.max_rps = 16.6; - mot3.mech_spec.mot_type = mot_c::mech_spec_s::DC; - mot3.mech_spec.pole_count = 4; - mot3.mech_spec.friction = 0.065;//0.0; - mot3.mech_spec.damping = 0.0000826;//0.0; - mot3.mech_spec.inertia = 0.000141; - - mot3.elec_spec.max_i = 4; - mot3.elec_spec.i = 2.2; - mot3.elec_spec.nm_a = 0.2727; - mot3.elec_spec.r = 15.2; - mot3.elec_spec.l = 0.0082;//0.030; - mot3.elec_spec.v_rps = 3.4;//5; - mot3.elec_spec.slip = 0; - - mot3.feedback.type = mot_c::feedback_s::RES; - mot3.feedback.count = 1; - mot3.feedback.res_offset = 0.0; - mot3.noise.sin_scale = 1.0; - mot3.noise.cos_scale = 1.0; - mot3.noise.sin_offset = 0.0; - mot3.noise.cos_offset = 0.0; - mot3.noise.var = 0.01; - - mot3.load.friction = 0.0; - mot3.load.load = 0.0; - mot3.load.damping = 0.0; - mot3.load.inertia = 0.0; - - cmd_c cmd; - cmd.reset(); - cmd.periode = 2; - cmd.amplitude = 1; - cmd.wave = cmd_c::CONST; - cmd.type = cmd_c::POS; - cmd.pos_res = 0.01; - cmd.vel_res = 0.01; - cmd.acc_res = 0.01; - - drive_c drive; - drive.dc = 50; - drive.pwm_scale = 0.9; - drive.pwm_res = 8400; - drive.pid_periode = 0.001; - drive.mot = &mot3; - drive.in = &cmd; - drive.input_cmd = input_cmd; - drive.input_feedback = input_feedback_real; - drive.pid = pid; - drive.output = output; - drive.reset(); - - cout << flush << "time pos pos2 pos3" << endl; - - int count = 0; - int pid_count = drive.pid_periode / sim_step; - - double vel0 = MIN(drive.dc * (2 * drive.pwm_scale - 1) / drive.mot->elec_spec.v_rps, drive.mot->mech_spec.max_rps) * 0.7; - double ind0 = vel0 * drive.mot->elec_spec.v_rps; - double volt0 = drive.dc * (2 * drive.pwm_scale - 1); - double cur0 = (volt0 - ind0) / drive.mot->elec_spec.r; - double torq0 = cur0 * drive.mot->elec_spec.nm_a; - double acc0 = torq0 / drive.mot->mech_spec.inertia; - - double vel1 = MIN(drive.dc * (2 * drive.pwm_scale - 1) / drive.mot->elec_spec.v_rps, drive.mot->mech_spec.max_rps) * 0.3; - double ind1 = vel1 * drive.mot->elec_spec.v_rps; - double volt1 = drive.dc * (2 * drive.pwm_scale - 1); - double cur1 = (volt1 - ind1) / drive.mot->elec_spec.r; - double torq1 = cur1 * drive.mot->elec_spec.nm_a; - double acc1 = torq1 / drive.mot->mech_spec.inertia; - - double a, b, y; - - a = (acc1 - acc0) / (vel1 - vel0); - b = acc0 - a * vel0; - std::vector in,out,foo; - int i = 0; - - for(sim_time = 0.0; sim_time < sim_end_time; sim_time += sim_step){ - drive.in->step(sim_step); - if(count == 0){ - drive.step(sim_step * pid_count); - } - count++; - count %= pid_count; - //drive.state.ctr = 1; - drive.output(&drive, sim_step); - drive.mot->step(sim_step); - - in.push_back(drive.mot->get_sin()*drive.mot->get_polarity()); - out.push_back(drive.mot->get_sin()*drive.mot->get_polarity()); - foo.push_back(sin((drive.mot->state.pos + drive.mot->feedback.res_offset) * drive.mot->feedback.count)); - //e_pos = (torq - drive.est.load) / drive.est.inertia * exp(-sim_time * mot.elec_spec.v_rps / drive.est.inertia * mot.elec_spec.nm_a / mot.elec_spec.r); - //y = a * drive.mot->state.vel + b; - - //cout << sim_time << ", " << drive.in->get_pos() << ", " << drive.mot->state.pos << ", " << drive.est.pos << ", " << drive.est.sin_avg << ", " << drive.est.sin_scale << ", " << drive.est.cos_avg << ", " << drive.est.cos_scale << endl; - //cout << sim_time << ", " << drive.mot->state.pos << ", " << drive.mot->state.vel << ", " << drive.mot->state.acc << ", " << drive.est.p << ", " << drive.est.v << ", " << drive.est.a << endl;//", " << drive.state.ctr << ", " << minus_(drive.in->get_pos(), drive.est.pos) << endl; - //cout << sim_time << ", " << "-15, " << drive.in->get_pos() * 5 - 15<< ", " << drive.state.ctr * 10 << ", " << drive.mot->state.cur << ", " << drive.mot->state.vel / 5 << ", " << drive.mot->state.pos * 5 - 15 << ", " << minus_(drive.in->state.pos, drive.mot->state.pos) * (-100) - 15 << endl;//", " << drive.state.ctr << ", " << minus_(drive.in->get_pos(), drive.est.pos) << endl; - //cout << sim_time/*drive.mot->state.vel*/ << ", " << drive.est.pos << ", " << drive.mot->state.pos << endl; - } - //out = tvd_1d_condat_worker(in, 0.05); - tvd_1d_condat(in, out, in.size(),0.05); - - for(sim_time = 0.0; sim_time < sim_end_time; sim_time += sim_step){ - cout << sim_time/*drive.mot->state.vel*/ << ", " << in[i] << ", " << out[i] << ", " << foo[i] << endl; - i++; - } - - system("gnuplot --persist gp"); - - return(0); -} diff --git a/sim/sim.h b/sim/sim.h deleted file mode 100644 index 8f9b06e5..00000000 --- a/sim/sim.h +++ /dev/null @@ -1,616 +0,0 @@ -#include -#include -#include -#include - -using namespace std; - -#define ABS(a) (((a) < 0) ? -(a) : (a)) -#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#define DEG(a) ((a)*M_PI/180.0) -#define RAD(a) ((a)*180.0/M_PI) -#define RAD(a) ((a)*180.0/M_PI) -#define SIGN(a) (((a) < 0) ? (-1) : (((a) > 0) ? (1) : (0))) - -double grand(){ - double ret = 0; - for(int i = 0; i < 12; i++){ - ret += (float)rand() / RAND_MAX; - } - return(ret - 6.0); -} - -double prand(){ - return(rand() * 2 * M_PI / RAND_MAX - M_PI); -} - -// double mod(double pos){ -// return(fmod(pos + M_PI, 2 * M_PI) - M_PI); -// } - -double mod(double a){ - while(a < -M_PI){ - a += 2.0 * M_PI; - } - while(a > M_PI){ - a -= 2.0 * M_PI; - } - return(a); -} - -double minus_(double a, double b){ - if(ABS(a - b) < M_PI){ - return(a - b); - } - else if(a > b){ - return(a - b - 2.0 * M_PI); - } - else{ - return(a - b + 2.0 * M_PI); - } -} - -class mot_c{ -public: - struct { - double pos; - double vel; - double acc; - double u; - double v; - double w; - double t; - double cur; - double volt; - double ind; - double torq; - int res_polarity; - } state; - - struct feedback_s{ - enum{ - ENC, - RES, - NONE - } type; - int count; - double res_offset; - int enc_offset; - } feedback; - - struct { - double max_i; - double i; - double r; - double l; - double nm_a; - double v_rps; - double slip; - } elec_spec; - - struct mech_spec_s{ - double t2; // term. time const - double max_rps; - int pole_count; - - enum{ - AC_SYNC, - AC_ASYNC, - DC - } mot_type; - - double friction; - double damping; - double inertia; // inertia - } mech_spec; - - struct{ - double var; - double sin_offset; - double sin_scale; - double cos_offset; - double cos_scale; - } noise; - - struct { - double friction; // friction (torque) - double load; // asym. torque - double damping; // damping (torque / vel) - double inertia; // inertia (torque / acc) - } load; - - void reset(); - void step(double periode); - - int get_enc(); - double get_sin(); - double get_cos(); - int get_polarity(); - - void set_volt(double u, double v, double w); -}; - -void mot_c::reset(){ - state.pos = 0.0;//prand(); - state.vel = 0.0; - state.acc = 0.0; - state.u = 0.0; - state.v = 0.0; - state.w = 0.0; - state.t = 20.0; - state.cur = 0.0; - state.volt = 0.0; - state.ind = 0.0; - state.res_polarity = 1.0; - feedback.enc_offset = state.pos; -} - -void mot_c::step(double periode){ - double d; - double q; - - state.res_polarity *= -1; - - switch(mech_spec.mot_type){ - case mech_spec_s::AC_SYNC: - d = 2/3 * (cos(state.pos * mech_spec.pole_count) * state.u + cos(state.pos * mech_spec.pole_count - 2/3 * M_PI) * state.v + cos(state.pos * mech_spec.pole_count + 2/3 * M_PI) * state.w); - q = 2/3 * (-sin(state.pos * mech_spec.pole_count) * state.u - sin(state.pos * mech_spec.pole_count - 2/3 * M_PI) * state.v - sin(state.pos * mech_spec.pole_count + 2/3 * M_PI) * state.w); - state.volt = q; - break; - case mech_spec_s::AC_ASYNC: - state.volt = 0.0; - break; - case mech_spec_s::DC: - state.volt = state.u - state.v; - break; - } - - state.ind = state.vel * elec_spec.v_rps; - state.cur += (state.volt - state.ind - state.cur * elec_spec.r) / elec_spec.l * periode; - state.cur = CLAMP(state.cur, -elec_spec.max_i, elec_spec.max_i); - //state.cur = (state.volt - state.ind) / elec_spec.r; - state.torq = state.cur * elec_spec.nm_a - (mech_spec.damping + load.damping) * state.vel + load.load; - if(abs(state.torq) < mech_spec.friction + load.friction){ - state.torq = 0.0; - } - else{ - state.torq = state.torq - SIGN(state.torq) * (mech_spec.friction + load.friction); - } - - state.acc = state.torq / (mech_spec.inertia + load.inertia); - state.vel += state.acc * periode; - state.pos += state.vel * periode; - state.pos = mod(state.pos); - if(state.cur > elec_spec.max_i){ - cerr << "MOT: cur > max_i: " << state.cur << endl; - } - if(state.vel > mech_spec.max_rps){ - cerr << "MOT: vel > max_v: " << state.vel << endl; - } -} - -void mot_c::set_volt(double u, double v, double w){ - state.u = u; - state.v = v; - state.w = w; -} - -int mot_c::get_enc(){ - return((int)((state.pos - feedback.enc_offset + 2 * M_PI) * feedback.count / 2 / M_PI) % feedback.count); -} - -double mot_c::get_sin(){ - return(sin((state.pos + feedback.res_offset) * feedback.count) * noise.sin_scale * state.res_polarity + noise.sin_offset + grand() * noise.var); -} - -double mot_c::get_cos(){ - return(cos((state.pos + feedback.res_offset) * feedback.count) * noise.cos_scale * state.res_polarity + noise.cos_offset + grand() * noise.var); -} - -int mot_c::get_polarity(){ - return(state.res_polarity); -} - -class cmd_c{ -public: - struct { - double time; - double pos; - double vel; - double acc; - } state; - - enum{ - POS, - POS_VEL, - POS_VEL_ACC, - VEL, - VEL_ACC - } type; - - enum{ - SINE, - SQUARE, - RAMP, - CONST - } wave; - - double periode; - double amplitude; - double max_vel; - double max_acc; - - double pos_res; - double vel_res; - double acc_res; - - void reset(); - void step(double periode); - - double get_pos(); - double get_vel(); - double get_acc(); -}; - -void cmd_c::reset(){ - state.time = 0.0; - state.pos = 0.0; - state.vel = 0.0; - state.acc = 0.0; -} - -void cmd_c::step(double s){ - state.time += s; - - switch(wave){ - case SINE: - state.pos = mod(sin(state.time / periode * 2 * M_PI) * amplitude); - state.vel = cos(state.time / periode * 2 * M_PI) * amplitude; - state.acc = -sin(state.time / periode * 2 * M_PI) * amplitude; - break; - case SQUARE: - state.pos = mod(((int)(state.time / periode * 2) % 2) * amplitude); - state.vel = 0; - state.acc = 0; - break; - case RAMP: - state.pos = mod(state.time * amplitude); - state.vel = 0; - state.acc = 0; - break; - case CONST: - state.pos = mod(amplitude); - state.vel = 0; - state.acc = 0; - break; - } -} - -double cmd_c::get_pos(){ - return((int)(state.pos / pos_res) * pos_res); -} - -double cmd_c::get_vel(){ - return((int)(state.vel / vel_res) * vel_res); -} - -double cmd_c::get_acc(){ - return((int)(state.acc / acc_res) * acc_res); -} - - -class drive_c{ -public: - struct cmd_s{ - double pos; - double vel; - double acc; - } cmd; - - double dc; - double pwm_scale; - int pwm_res; - double pid_periode; - - struct { - double offset; - double sin_scale; - double sin_avg; - double cos_scale; - double cos_avg; - double res_var; - - double pos; - double vel; - double acc; - double cur; - - double friction; - double load; - double damping; - double inertia; - - double p; - double v; - double a; - } est; - - struct { - double mag_pos; - double mag_vel; - double ctr; - } state; - - mot_c* mot; - cmd_c* in; - - void reset(); - void step(double periode); - - void (*input_cmd)(drive_c* drv, double periode); - void (*input_feedback)(drive_c* drv, double periode); - void (*pid)(drive_c* drv, double periode); - void (*output)(drive_c* drv, double periode); - - void set_pos(double pos); - void set_pos_vel(double pos, double vel); - void set_pos_vel_acc(double pos, double vel, double acc); - void set_vel(double pos); - void set_vel_acc(double pos, double acc); -}; - -void drive_c::reset(){ - cmd.pos = 0.0; - cmd.vel = 0.0; - cmd.acc = 0.0; - - est.offset = 0.0; - est.sin_scale = 1.0; - est.cos_scale = 1.0; - est.sin_avg = 0.0; - est.cos_avg = 0.0; - est.res_var = 0.0; - - est.friction = mot->mech_spec.friction; - est.load = 0.0; - est.damping = mot->mech_spec.damping; - est.inertia = mot->mech_spec.inertia; - - est.pos = 0.0; - est.vel = 0.0; - est.acc = 0.0; - est.cur = 0.0; - - state.mag_pos = 0.0; - state.mag_vel = 0.0; - state.ctr = 0.0; -} - -void drive_c::step(double periode){ - input_cmd(this, periode); - input_feedback(this, periode); - pid(this, periode); - output(this, periode); -} - -void input_cmd(drive_c* drv, double periode){ - double tp, tv; - - tp = drv->cmd.pos; - tv = drv->cmd.vel; - - switch(drv->in->type){ - case cmd_c::POS: - drv->cmd.pos = drv->in->get_pos(); - drv->cmd.vel = (drv->cmd.pos - tp) / periode; - drv->cmd.acc = (drv->cmd.vel - tv) / periode; - break; - case cmd_c::POS_VEL: - drv->cmd.pos = drv->in->get_pos(); - drv->cmd.vel = drv->in->get_vel();; - drv->cmd.acc = (drv->cmd.vel - tv) / periode; - break; - case cmd_c::POS_VEL_ACC: - drv->cmd.pos = drv->in->get_pos(); - drv->cmd.vel = drv->in->get_vel();; - drv->cmd.acc = drv->in->get_acc(); - break; - case cmd_c::VEL: - drv->cmd.pos = drv->cmd.pos + drv->cmd.vel * periode; - drv->cmd.vel = drv->in->get_vel();; - drv->cmd.acc = (drv->cmd.vel - tv) / periode; - break; - case cmd_c::VEL_ACC: - drv->cmd.pos = drv->cmd.pos + drv->cmd.vel * periode; - drv->cmd.vel = drv->in->get_vel();; - drv->cmd.acc = drv->in->get_acc(); - break; - } -} - -void input_feedback(drive_c* drv, double periode){ - double t1, t2; - static double sin_avg_amp = 1.0; - static double cos_avg_amp = 1.0; - static double r = 1.0; - double dpos = 0.0; - double v = 0.0; - static double i_sum; - double p = 0.05; - double i = 1 * periode; - double vlo = 0.0 * periode; - - static int point = 0; - const int hist_size = 10; - static double pos_hist[hist_size]; - static double vel_hist[hist_size]; - static double acc_hist[hist_size]; - - t1 = drv->est.pos; - - switch(drv->mot->feedback.type){ - case mot_c::feedback_s::ENC: - drv->est.pos = mod(drv->mot->get_enc() * 2 * M_PI / drv->mot->feedback.count - drv->est.offset); - break; - case mot_c::feedback_s::RES: - drv->est.sin_avg = 0.995 * drv->est.sin_avg + 0.005 * drv->mot->get_sin(); - drv->est.cos_avg = 0.995 * drv->est.cos_avg + 0.005 * drv->mot->get_cos(); - // sin_avg_amp = 0.5 * sin_avg_amp + 0.5 * (drv->mot->get_sin() - drv->est.sin_avg) / drv->est.sin_scale * drv->mot->get_polarity(); - // cos_avg_amp = 0.5 * cos_avg_amp + 0.5 * (drv->mot->get_cos() - drv->est.cos_avg) / drv->est.cos_scale * drv->mot->get_polarity(); - // - // r = 0.99 * r + 0.01 * (sin_avg_amp * sin_avg_amp + cos_avg_amp * cos_avg_amp); - // - // if(ABS(sin_avg_amp) < 0.01){ - // drv->est.cos_scale -= 0.001 * SIGN(1 - cos_avg_amp); - // } - // - // if(ABS(cos_avg_amp) < 0.01){ - // drv->est.sin_scale -= 0.001 * SIGN(1 - sin_avg_amp); - // } - // - // if(ABS(r - 1.0) > 0.6){ - // //cerr << "res error r: " << r << endl; - // } - - - dpos = (drv->mot->get_sin() - drv->est.sin_avg) / drv->est.sin_scale * drv->mot->get_polarity() * cos(drv->est.pos + drv->est.offset) - (drv->mot->get_cos() - drv->est.cos_avg) / drv->est.cos_scale * drv->mot->get_polarity() * sin(drv->est.pos + drv->est.offset); - i_sum += dpos * i + vlo * (drv->state.ctr * drv->dc - drv->est.vel * drv->mot->elec_spec.v_rps) / drv->mot->elec_spec.r * drv->mot->elec_spec.nm_a * periode; - dpos = p * dpos + i_sum; - drv->est.pos += dpos; - drv->est.pos = mod(drv->est.pos); - pos_hist[point] = drv->est.pos; - vel_hist[point] = minus_(pos_hist[(point) % hist_size], pos_hist[(point + hist_size - 2) % hist_size]) / (2 * periode); - acc_hist[point] = minus_(vel_hist[(point) % hist_size], vel_hist[(point + hist_size - 2) % hist_size]) / (2 * periode); - point++; - - point %= hist_size; - //drv->est.vel = i_sum / periode; - drv->est.pos = mod(atan2((drv->mot->get_sin() - drv->est.sin_avg) / drv->est.sin_scale * drv->mot->get_polarity(), (drv->mot->get_cos() - drv->est.cos_avg) / drv->est.cos_scale * drv->mot->get_polarity()) - drv->est.offset); - break; - case mot_c::feedback_s::NONE: - break; - } - - double a = 0.0; - v = 0.0; - p = 0.0; - double x = 0.0; - - for(int j = 0; j < hist_size; j++){ - a += acc_hist[(point + j) % hist_size]; - } - a /= hist_size; - a *= 0.5; - - for(int j = 0; j < hist_size; j++){ - x = (j - hist_size / 2.0) * periode; - v += vel_hist[(point + j) % hist_size] - (2 * a * x); - } - v /= hist_size; - - for(int j = 0; j < hist_size; j++){ - x = (j - hist_size / 2.0) * periode; - p += pos_hist[(point + j) % hist_size] - (a * x * x + v * x); - } - p /= hist_size; - - x = hist_size / 2.0 * periode; - drv->est.p = (a * x * x + v * x + p); - drv->est.v = (2 * a * x + v); - drv->est.a = (2 * a); - - drv->est.pos = drv->mot->state.pos; - - //drv->est.pos = drv->est.p; - - // t2 = drv->est.vel; - // drv->est.vel = (drv->est.pos - t1) / periode; - // drv->est.acc = (drv->est.vel - t2) / periode; -} - -void input_feedback_real(drive_c* drv, double periode){ - drv->est.pos = drv->mot->state.pos; - drv->est.vel = drv->mot->state.vel; - drv->est.acc = drv->mot->state.acc; -} - -void pid(drive_c* drv, double periode){ - double p = 1000; // kp - double i = 10000 * periode; // ki - double d = 0.6 / periode; // kd - double dd = 0.0 / periode; // rel. vel. kd - double in = 0.0; // ind. kp - - double dc_scale = 1.0 / drv->dc; // dc voltage scale - double ind = drv->mot->state.vel * drv->mot->elec_spec.v_rps / drv->dc; - - double e = minus_(drv->cmd.pos, drv->est.pos); - static double e_old = 0; - static double i_sum = 0; - - i_sum += e; - //i_sum -= - drv->state.ctr = p * e; - drv->state.ctr += i * i_sum; - drv->state.ctr += d * (e - e_old); - if(abs(e) > 0.01){ - drv->state.ctr += dd * (e - e_old) / e; - } - drv->state.ctr *= dc_scale; - drv->state.ctr += in * ind; - - drv->state.ctr = CLAMP(drv->state.ctr, -1, 1); - // if(ABS(drv->est.vel) >= drv->mot->mech_spec.max_rps * 0.7){ - // drv->state.ctr = 0.0; - // } - - if(abs(drv->state.ctr) >= 0.99){ - i_sum -= e; - } - i_sum = CLAMP(i_sum, -1/i, 1/i); - - e_old = e; -} - -void pid2(drive_c* drv, double periode){ - double ind = drv->est.vel * drv->mot->elec_spec.v_rps; - double max_volt_pos = drv->dc * drv->pwm_scale - ind; - double max_cur_pos = max_volt_pos / drv->mot->elec_spec.r; - double max_torq_pos = max_cur_pos * drv->mot->elec_spec.nm_a; - max_torq_pos -= drv->est.friction; - max_torq_pos -= drv->est.load; - max_torq_pos -= drv->est.damping * drv->est.vel; - double max_acc_pos = max_torq_pos / drv->est.inertia; - double max_dvel_pos = max_acc_pos * periode; - - double max_volt_neg = -drv->dc * drv->pwm_scale - ind; - double max_cur_neg = max_volt_neg / drv->mot->elec_spec.r; - double max_torq_neg = max_cur_neg * drv->mot->elec_spec.nm_a; - max_torq_neg -= drv->est.friction; - max_torq_neg += drv->est.load; - max_torq_neg -= drv->est.damping * drv->est.vel; - double max_acc_neg = max_torq_neg / drv->est.inertia; - double max_dvel_neg = max_acc_neg * periode; - - - - drv->state.ctr = 0.0; -} - -void output(drive_c* drv, double periode){ - double u, v, w; - - switch(drv->mot->mech_spec.mot_type){ - case mot_c::mech_spec_s::AC_SYNC: - case mot_c::mech_spec_s::AC_ASYNC: - case mot_c::mech_spec_s::DC: - u = ((int)((drv->state.ctr * drv->pwm_scale + 1) / 2.0 * drv->pwm_res)) * drv->dc / drv->pwm_res; - v = ((int)((drv->state.ctr * drv->pwm_scale * (-1) + 1) / 2.0 * drv->pwm_res)) * drv->dc / drv->pwm_res; - w = 0; - break; - } - - drv->mot->set_volt(u, v, w); -} diff --git a/tools/checkcrc.py b/tools/checkcrc.py deleted file mode 100755 index a814f024..00000000 --- a/tools/checkcrc.py +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env python -import binascii -import sys - -buf = open(sys.argv[1],'rb').read() -buf = (binascii.crc32(buf) & 0xFFFFFFFF) -if buf == 0: - print "crc ok!" - sys.exit(0) -else: - print "This should not happen. Please report a bug." - sys.exit(-1)