SPS.ino 21 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060
  1. /*
  2. SPS System mit dem Arduino.
  3. Version 0.13.0
  4. 15.06.2021
  5. - fea: ESP32 implementation
  6. Version 0.12.4
  7. 10.06.2021
  8. - bug: pop not working
  9. - bug: a = not a not working
  10. Version 0.12.3
  11. 10.06.2021
  12. - adding auto programming feature for the SPS Emulator
  13. Version 0.12.2
  14. 07.06.2021
  15. - bug with servo in 4-bit mode, evaluate the full 8 bit.
  16. Version 0.12.1
  17. 03.09.2019
  18. - changing the variable names in debug mode
  19. Version 0.12
  20. 27.01.2019
  21. - adding demo program,
  22. 11.01.2018
  23. - some refactoring
  24. 07.01.2018
  25. - programming: 1/2 duty cycle for 0 values in address display
  26. Version 0.11
  27. 17.12.2018
  28. - adding Shift left and shift right to register A
  29. Version 0.10
  30. 7.12.2018
  31. - new define for serial programming
  32. 18.11.2018 WKLA
  33. - new standard programming mode
  34. I added a new programming mode for the default programming, because i thing the old one was a little bit clumsy.
  35. the new one has a nicer interface, as you now always know where you are.
  36. Starting with PRG pushed after Reset.
  37. as a result, all LEDs will shortly blink
  38. now you are in programming mode.
  39. the D1 LED will blink
  40. the higher nibble of the address will be shown
  41. the D2 LED will blink
  42. the lower nibble of the address will be shown
  43. the D3 LED will blink
  44. the command part (high nibble) will be shown
  45. with SEL you can step thru all commands
  46. PRG will save the command
  47. the D4 LED will blink
  48. the data part (low nibble) will be shown
  49. with SEL you can step thru all datas
  50. PRG will save the data
  51. if the new value has been changed, all LEDs will flash as the byte will be written to the EEPROM
  52. address will be increased and now it will start with blinking of the D1 LED
  53. To leave the programming simply push reset.
  54. Version 0.9
  55. 18.11.2018 WKLA
  56. - BUGs entfernt. Release.
  57. 10.11.2018 WKLA
  58. - Implementierung Tone Befehl
  59. Version 0.8
  60. 06.11.2018 WKLA
  61. - Umstellung auf dbgOut
  62. - Display TM1637 Anbindung
  63. Version 0.7
  64. 24.09.2012 WKLA
  65. - neue Berechnung A = B - A und Swap A,B...
  66. - Stack auf 16 Bytes berschränkt, wird zu oft gepusht, werden die alten Werte rausgeschoben.
  67. Basierd auf dem TPS System vom elektronik-labor.
  68. Erweiterungen:
  69. - es können bis zu 6 Unterroutinen definiert werden und diese direkt angesprungen werden.
  70. - neben return gibt's auch einen restart
  71. - 2 Servoausgänge für übliche RC Servos. (10° Auflösung in Nibble Modus, <1° Auflösung im Bytemodus)
  72. ACHTUNG: Servo und PWM Ausgänge sind nicht mischbar und können auch nicht gleichzeitig benutzt werden.
  73. - 2 RC Eingänge (16 Schritte auflösung im nibble Modus, Mitte 8, 255 Schritte im Byte Modus)
  74. - fkt. auch mit einem ATTiny84 (44 ist leider auf GRund der Programmgröße nicht mehr für den erweiterten Befehlssatz möglich)
  75. - call stack von bis zu 16 Unterfunktionen
  76. - neue Register e,f
  77. */
  78. /*
  79. Here are the defines used in this software to control special parts of the implementation
  80. #define SPS_USE_DISPLAY: using a external TM1637 Display for displaying address and data at one time
  81. #define SPS_RECEIVER: using a RC receiver input
  82. #define SPS_ENHANCEMENT: all of the other enhancments
  83. #define SPS_SERVO: using servo outputs
  84. #define SPS_TONE: using a tone output
  85. #define SPS_SERIAL_PRG: activates the serial programming feature
  86. */
  87. // Program im Debugmodus kompilieren, dann werden zus. Ausgaben auf die serielle Schnittstelle geschrieben.
  88. #define debug
  89. // defining different hardware platforms
  90. #ifdef __AVR_ATmega328P__
  91. //#define SPS_USE_DISPLAY
  92. //#define SPS_RECEIVER
  93. //#define SPS_ENHANCEMENT
  94. //#define SPS_SERIAL_PRG
  95. //#define SPS_SERVO
  96. //#define SPS_TONE
  97. #endif
  98. #ifdef ESP32
  99. //#define SPS_RECEIVER (not implementted yet)
  100. #define SPS_ENHANCEMENT
  101. #define SPS_SERIAL_PRG
  102. //#define SPS_SERVO
  103. //#define SPS_TONE
  104. #endif
  105. #ifdef __AVR_ATtiny84__
  106. #define SPS_ENHANCEMENT
  107. #define SPS_SERIAL_PRG
  108. #define SPS_SERVO
  109. //#define SPS_TONE
  110. #endif
  111. #ifdef __AVR_ATtiny861__
  112. #define SPS_RCRECEIVER
  113. #define SPS_ENHANCEMENT
  114. #define SPS_SERIAL_PRG
  115. //#define SPS_SERVO
  116. #define SPS_TONE
  117. #endif
  118. #ifdef __AVR_ATtiny4313__
  119. #define SPS_RCRECEIVER
  120. #endif
  121. // libraries
  122. #include "debug.h"
  123. #include "makros.h"
  124. #include "EEPROM_store.h"
  125. #ifdef ESP32
  126. //#include <analogWrite.h>
  127. #include <ESP32Servo.h>
  128. #endif
  129. #ifdef SPS_SERVO
  130. #if defined(__AVR_ATmega328P__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny861__) || defined(__AVR_ATtiny4313__)
  131. #include <Servo.h>
  132. #endif
  133. #endif
  134. #ifdef SPS_ENHANCEMENT
  135. #include <avdweb_Switch.h>
  136. #endif
  137. #ifdef SPS_TONE
  138. #include "notes.h"
  139. #ifdef ESP32
  140. #include <ESP32Tone.h>
  141. #endif
  142. #endif
  143. #include "hardware.h"
  144. // Commands
  145. const byte PORT = 0x10;
  146. const byte DELAY = 0x20;
  147. const byte JUMP_BACK = 0x30;
  148. const byte SET_A = 0x40;
  149. const byte IS_A = 0x50;
  150. const byte A_IS = 0x60;
  151. const byte CALC = 0x70;
  152. const byte PAGE = 0x80;
  153. const byte JUMP = 0x90;
  154. const byte C_COUNT = 0xA0;
  155. const byte D_COUNT = 0xB0;
  156. const byte SKIP_IF = 0xC0;
  157. const byte CALL = 0xD0;
  158. const byte CALL_SUB = 0xE0;
  159. const byte CMD_BYTE = 0xF0;
  160. // debouncing with 100ms
  161. const byte DEBOUNCE = 100;
  162. // sub routines
  163. const byte subCnt = 7;
  164. word subs[subCnt];
  165. // the actual address of the program
  166. word addr;
  167. // page register
  168. word page;
  169. // defining register
  170. byte a, b, c, d;
  171. #ifdef SPS_ENHANCEMENT
  172. byte e, f;
  173. #endif
  174. #ifdef SPS_ENHANCEMENT
  175. const byte SAVE_CNT = 16;
  176. #else
  177. const byte SAVE_CNT = 1;
  178. #endif
  179. word saveaddr[SAVE_CNT];
  180. byte saveCnt;
  181. #ifdef SPS_ENHANCEMENT
  182. byte stack[SAVE_CNT];
  183. byte stackCnt;
  184. #endif
  185. unsigned long tmpValue;
  186. #ifdef SPS_SERVO
  187. Servo servo1;
  188. Servo servo2;
  189. #endif
  190. byte data = 0;
  191. byte cmd = 0;
  192. void setup() {
  193. pinMode(Dout_1, OUTPUT);
  194. pinMode(Dout_2, OUTPUT);
  195. pinMode(Dout_3, OUTPUT);
  196. pinMode(Dout_4, OUTPUT);
  197. pinMode(PWM_1, OUTPUT);
  198. pinMode(PWM_2, OUTPUT);
  199. pinMode(Din_1, INPUT_PULLUP);
  200. pinMode(Din_2, INPUT_PULLUP);
  201. pinMode(Din_3, INPUT_PULLUP);
  202. pinMode(Din_4, INPUT_PULLUP);
  203. pinMode(SW_PRG, INPUT_PULLUP);
  204. pinMode(SW_SEL, INPUT_PULLUP);
  205. #ifdef ESP32
  206. ESP32PWM::allocateTimer(0);
  207. ESP32PWM::allocateTimer(1);
  208. ESP32PWM::allocateTimer(2);
  209. ESP32PWM::allocateTimer(3);
  210. #endif
  211. digitalWrite(Dout_1, 1);
  212. delay(1000);
  213. digitalWrite(Dout_1, 0);
  214. #ifdef SPS_USE_DISPLAY
  215. initDisplay();
  216. #endif
  217. // Serielle Schnittstelle einstellen
  218. #ifndef __AVR_ATtiny84__
  219. initDebug();
  220. #endif
  221. prgDemoPrg();
  222. doReset();
  223. if (digitalRead(SW_PRG) == 0) {
  224. programMode();
  225. }
  226. #ifdef SPS_ENHANCEMENT
  227. pinMode(LED_BUILTIN, OUTPUT);
  228. #endif
  229. #ifdef SPS_SERIAL_PRG
  230. initSerialPrg();
  231. if (digitalRead(SW_SEL) == 0) {
  232. serialPrg();
  233. }
  234. #endif
  235. }
  236. void doReset() {
  237. dbgOutLn("Reset");
  238. #ifdef SPS_SERVO
  239. servo1.detach();
  240. servo2.detach();
  241. #endif
  242. for (int i = 0; i < subCnt; i++) {
  243. subs[i] = 0;
  244. }
  245. readProgram();
  246. addr = 0;
  247. page = 0;
  248. saveCnt = 0;
  249. a = 0;
  250. b = 0;
  251. c = 0;
  252. d = 0;
  253. #ifdef SPS_ENHANCEMENT
  254. e = 0;
  255. f = 0;
  256. stackCnt = 0;
  257. for (int i = 0; i < SAVE_CNT; i++) {
  258. stack[i] = 0;
  259. }
  260. #endif
  261. }
  262. /*
  263. getting all addresses of sub programms
  264. */
  265. void readProgram() {
  266. dbgOutLn("Read program");
  267. word addr = 0;
  268. for ( addr = 0; addr <= STORESIZE; addr++) {
  269. byte value = readbyte(addr);
  270. #ifdef debug
  271. dbgOutLn();
  272. dbgOut2(addr, HEX);
  273. dbgOut(": ");
  274. #endif
  275. byte cmd = (value & 0xF0);
  276. byte data = (value & 0x0F);
  277. dbgOut2(cmd >> 4, HEX);
  278. dbgOut2(data, HEX);
  279. if (value == 0xFF) {
  280. // ende des Programms
  281. break;
  282. }
  283. if (cmd == CALL_SUB) {
  284. if (data >= 8) {
  285. data = data - 8;
  286. subs[data] = addr + 1;
  287. dbgOut(", sub def ");
  288. dbgOut(data);
  289. }
  290. }
  291. #ifdef SPS_SERVO
  292. if ((cmd == IS_A) && (data == 0x0B)) {
  293. if (!servo1.attached()) {
  294. dbgOut(": attach Srv1");
  295. #ifdef ESP32
  296. servo1.setPeriodHertz(50);
  297. #endif
  298. servo1.attach(SERVO_1);
  299. }
  300. } else if ((cmd == CMD_BYTE) && (data == 0x06)) {
  301. if (!servo1.attached()) {
  302. dbgOut(": attach Srv1");
  303. #ifdef ESP32
  304. servo1.setPeriodHertz(50);
  305. #endif
  306. servo1.attach(SERVO_1);
  307. }
  308. } else if ((cmd == IS_A) && (data == 0x0C)) {
  309. if (!servo2.attached()) {
  310. dbgOut(": attach Srv2");
  311. #ifdef ESP32
  312. servo2.setPeriodHertz(50);
  313. #endif
  314. servo2.attach(SERVO_2);
  315. }
  316. } else if ((cmd == CMD_BYTE) && (data == 0x07)) {
  317. if (!servo2.attached()) {
  318. dbgOut(": attach Srv2");
  319. #ifdef ESP32
  320. servo2.setPeriodHertz(50);
  321. #endif
  322. servo2.attach(SERVO_2);
  323. }
  324. }
  325. #endif
  326. }
  327. dbgOutLn();
  328. }
  329. /*
  330. main loop
  331. */
  332. void loop() {
  333. #ifdef SPS_SERIAL_PRG
  334. if (Serial.available() > 0) {
  335. while (Serial.available() > 0) {
  336. char myChar = Serial.read();
  337. if (myChar == 'p') {
  338. serialPrg();
  339. Serial.println("end of inline programming");
  340. doReset();
  341. }
  342. }
  343. }
  344. #endif
  345. byte value = readbyte(addr);
  346. cmd = (value & 0xF0);
  347. data = (value & 0x0F);
  348. debugOutputRegister();
  349. addr = addr + 1;
  350. switch (cmd) {
  351. case PORT:
  352. doPort(data);
  353. break;
  354. case DELAY:
  355. doDelay(data);
  356. break;
  357. case JUMP_BACK:
  358. doJumpBack(data);
  359. break;
  360. case SET_A:
  361. doSetA(data);
  362. break;
  363. case A_IS:
  364. doAIs(data);
  365. break;
  366. case IS_A:
  367. doIsA(data);
  368. break;
  369. case CALC:
  370. doCalc(data);
  371. break;
  372. case PAGE:
  373. doPage(data);
  374. break;
  375. case JUMP:
  376. doJump(data);
  377. break;
  378. case C_COUNT:
  379. doCCount(data);
  380. break;
  381. case D_COUNT:
  382. doDCount(data);
  383. break;
  384. case SKIP_IF:
  385. doSkipIf(data);
  386. break;
  387. case CALL:
  388. doCall(data);
  389. break;
  390. case CALL_SUB:
  391. doCallSub(data);
  392. break;
  393. case CMD_BYTE:
  394. doByte(data);
  395. break;
  396. default:
  397. ;
  398. }
  399. if (addr > STORESIZE) {
  400. doReset();
  401. }
  402. }
  403. void debugOutputRegister() {
  404. dbgOut2(addr, HEX); dbgOut(":"); dbgOut2(cmd >> 4, HEX); dbgOut(","); dbgOut2(data, HEX);
  405. dbgOut(",reg:"); dbgOut2(a, HEX); dbgOut(","); dbgOut2(b, HEX); dbgOut(",");
  406. dbgOut2(c, HEX); dbgOut(","); dbgOut2(d, HEX); dbgOut(",");
  407. #ifdef SPS_ENHANCEMENT
  408. dbgOut2(e, HEX); dbgOut(","); dbgOut2(f, HEX);
  409. dbgOut(", s:"); dbgOut2(stackCnt, HEX); dbgOut(":");
  410. for (int i = 0; i < SAVE_CNT; i++) {
  411. dbgOut2(stack[i], HEX); dbgOut(",");
  412. }
  413. #endif
  414. dbgOutLn();
  415. }
  416. /*
  417. output to port
  418. */
  419. void doPort(byte data) {
  420. digitalWrite(Dout_1, (data & 0x01) > 0);
  421. digitalWrite(Dout_2, (data & 0x02) > 0);
  422. digitalWrite(Dout_3, (data & 0x04) > 0);
  423. digitalWrite(Dout_4, (data & 0x08) > 0);
  424. }
  425. /*
  426. delay in ms
  427. */
  428. void doDelay(byte data) {
  429. dbgOut("dly: ");
  430. dbgOutLn2(data, HEX);
  431. switch (data) {
  432. case 0:
  433. delay(1);
  434. break;
  435. case 1:
  436. delay(2);
  437. break;
  438. case 2:
  439. delay(5);
  440. break;
  441. case 3:
  442. delay(10);
  443. break;
  444. case 4:
  445. delay(20);
  446. break;
  447. case 5:
  448. delay(50);
  449. break;
  450. case 6:
  451. delay(100);
  452. break;
  453. case 7:
  454. delay(200);
  455. break;
  456. case 8:
  457. delay(500);
  458. break;
  459. case 9:
  460. delay(1000);
  461. break;
  462. case 10:
  463. delay(2000);
  464. break;
  465. case 11:
  466. delay(5000);
  467. break;
  468. case 12:
  469. delay(10000);
  470. break;
  471. case 13:
  472. delay(20000);
  473. break;
  474. case 14:
  475. delay(30000);
  476. break;
  477. case 15:
  478. delay(60000);
  479. break;
  480. default:
  481. break;
  482. }
  483. }
  484. /*
  485. jump relative back
  486. */
  487. void doJumpBack(byte data) {
  488. addr = addr - data - 1;
  489. }
  490. /*
  491. a = data
  492. */
  493. void doSetA(byte data) {
  494. a = data;
  495. }
  496. /*
  497. a = somthing;
  498. */
  499. void doAIs(byte data) {
  500. switch (data) {
  501. case 1:
  502. a = b;
  503. break;
  504. case 2:
  505. a = c;
  506. break;
  507. case 3:
  508. a = d;
  509. break;
  510. case 4:
  511. a = digitalRead(Din_1) + (digitalRead(Din_2) << 1) + (digitalRead(Din_3) << 2) + (digitalRead(Din_4) << 3);
  512. break;
  513. case 5:
  514. a = digitalRead(Din_1);
  515. break;
  516. case 6:
  517. a = digitalRead(Din_2);
  518. break;
  519. case 7:
  520. a = digitalRead(Din_3);
  521. break;
  522. case 8:
  523. a = digitalRead(Din_4);
  524. break;
  525. #ifndef __AVR_ATtiny4313__
  526. case 9:
  527. tmpValue = getAnalog(ADC_0);
  528. a = tmpValue >> 4; //(Umrechnen auf 4 bit)
  529. break;
  530. case 10:
  531. tmpValue = getAnalog(ADC_1);
  532. a = tmpValue >> 4; //(Umrechnen auf 4 bit)
  533. break;
  534. #else
  535. case 9:
  536. a = digitalRead(ADC_0);
  537. break;
  538. case 10:
  539. a = digitalRead(ADC_1);
  540. break;
  541. #endif
  542. #ifdef SPS_RCRECEIVER
  543. case 11:
  544. tmpValue = pulseIn(RC_0, HIGH, 100000);
  545. if (tmpValue < 1000) {
  546. tmpValue = 1000;
  547. }
  548. if (tmpValue > 2000) {
  549. tmpValue = 2000;
  550. }
  551. a = (tmpValue - 1000) / 64; //(Umrechnen auf 4 bit)
  552. dbgOut("RC1:");
  553. dbgOut(tmpValue);
  554. dbgOut("=");
  555. dbgOutLn(a);
  556. break;
  557. case 12:
  558. tmpValue = pulseIn(RC_1, HIGH, 100000);
  559. if (tmpValue < 1000) {
  560. tmpValue = 1000;
  561. }
  562. if (tmpValue > 2000) {
  563. tmpValue = 2000;
  564. }
  565. a = (tmpValue - 1000) / 64; //(Umrechnen auf 4 bit)
  566. dbgOut("RC2:");
  567. dbgOut(tmpValue);
  568. dbgOut("=");
  569. dbgOutLn(a);
  570. break;
  571. #endif
  572. #ifdef SPS_ENHANCEMENT
  573. case 13:
  574. a = e;
  575. break;
  576. case 14:
  577. a = f;
  578. break;
  579. case 15:
  580. dbgOut("pop ");
  581. dbgOutLn(stackCnt);
  582. if (stackCnt > 0) {
  583. stackCnt -= 1;
  584. a = stack[stackCnt];
  585. } else {
  586. a = 0;
  587. }
  588. break;
  589. #endif
  590. default:
  591. break;
  592. }
  593. }
  594. /*
  595. somthing = a;
  596. */
  597. void doIsA(byte data) {
  598. switch (data) {
  599. #ifdef SPS_ENHANCEMENT
  600. case 0:
  601. swap(a, b, byte);
  602. break;
  603. #endif
  604. case 1:
  605. b = a;
  606. break;
  607. case 2:
  608. c = a;
  609. break;
  610. case 3:
  611. d = a;
  612. break;
  613. case 4:
  614. doPort(a);
  615. break;
  616. case 5:
  617. digitalWrite(Dout_1, (a & 0x01) > 0);
  618. break;
  619. case 6:
  620. digitalWrite(Dout_2, (a & 0x01) > 0);
  621. break;
  622. case 7:
  623. digitalWrite(Dout_3, (a & 0x01) > 0);
  624. break;
  625. case 8:
  626. digitalWrite(Dout_4, (a & 0x01) > 0);
  627. break;
  628. case 9:
  629. tmpValue = (a & 0x0f) * 16;
  630. dbgOut("PWM1:");
  631. dbgOutLn(tmpValue);
  632. analogWrite(PWM_1, tmpValue);
  633. break;
  634. case 10:
  635. tmpValue = (a & 0x0f) * 16;
  636. dbgOut("PWM2:");
  637. dbgOutLn(tmpValue);
  638. analogWrite(PWM_2, tmpValue);
  639. break;
  640. #ifdef SPS_SERVO
  641. case 11:
  642. if (servo1.attached()) {
  643. tmpValue = ((a & 0x0f) * 10) + 10;
  644. dbgOut("Srv1:");
  645. dbgOutLn(tmpValue);
  646. servo1.write(tmpValue);
  647. }
  648. break;
  649. case 12:
  650. if (servo2.attached()) {
  651. tmpValue = ((a & 0x0f) * 10) + 10;
  652. dbgOut("Srv2:");
  653. dbgOutLn(tmpValue);
  654. servo2.write(tmpValue);
  655. }
  656. break;
  657. #endif
  658. #ifdef SPS_ENHANCEMENT
  659. case 13:
  660. e = a;
  661. break;
  662. case 14:
  663. f = a;
  664. break;
  665. case 15:
  666. dbgOut("push ");
  667. dbgOutLn(stackCnt);
  668. if (stackCnt < SAVE_CNT) {
  669. stack[stackCnt] = a;
  670. stackCnt += 1;
  671. }
  672. else {
  673. for (int i = 1; i <= SAVE_CNT; i++) {
  674. stack[i - 1] = stack[i];
  675. }
  676. stack[stackCnt] = a;
  677. }
  678. break;
  679. #endif
  680. default:
  681. break;
  682. }
  683. }
  684. /*
  685. calculations
  686. */
  687. void doCalc(byte data) {
  688. switch (data) {
  689. case 1:
  690. a = a + 1;
  691. break;
  692. case 2:
  693. a = a - 1;
  694. break;
  695. case 3:
  696. a = a + b;
  697. break;
  698. case 4:
  699. a = a - b;
  700. break;
  701. case 5:
  702. a = a * b;
  703. break;
  704. case 6:
  705. a = a / b;
  706. break;
  707. case 7:
  708. a = a & b;
  709. break;
  710. case 8:
  711. a = a | b;
  712. break;
  713. case 9:
  714. a = a ^ b;
  715. break;
  716. case 10:
  717. a = ~a;
  718. break;
  719. #ifdef SPS_ENHANCEMENT
  720. case 11:
  721. a = a % b;
  722. break;
  723. case 12:
  724. a = a + 16 * b;
  725. break;
  726. case 13:
  727. a = b - a;
  728. break;
  729. case 14:
  730. a = a >> 1;
  731. break;
  732. case 15:
  733. a = a << 1;
  734. break;
  735. #endif
  736. default:
  737. break;
  738. }
  739. a = a & 0xFF;
  740. #ifndef SPS_ENHANCEMENT
  741. a = a & 15;
  742. #endif
  743. }
  744. /*
  745. setting page
  746. */
  747. void doPage(byte data) {
  748. page = data * 16;
  749. }
  750. /*
  751. jump absolute
  752. */
  753. void doJump(byte data) {
  754. #ifdef debug
  755. dbgOut("J");
  756. dbgOut2(page >> 4, HEX);
  757. dbgOutLn2(data, HEX);
  758. #endif
  759. addr = page + data;
  760. }
  761. /*
  762. counting with c register
  763. */
  764. void doCCount(byte data) {
  765. if (c > 0) {
  766. c -= 1;
  767. c = c & 0x0F;
  768. doJump(data);
  769. }
  770. }
  771. /*
  772. counting with d register
  773. */
  774. void doDCount(byte data) {
  775. if (d > 0) {
  776. d -= 1;
  777. d = d & 0x0F;
  778. doJump(data);
  779. }
  780. }
  781. /*
  782. simple condition = true, skip next command
  783. */
  784. void doSkipIf(byte data) {
  785. bool skip = false;
  786. switch (data) {
  787. #ifdef SPS_ENHANCEMENT
  788. case 0:
  789. skip = (a == 0);
  790. break;
  791. #endif
  792. case 1:
  793. skip = (a > b);
  794. break;
  795. case 2:
  796. skip = (a < b);
  797. break;
  798. case 3:
  799. skip = (a == b);
  800. break;
  801. case 4:
  802. skip = digitalRead(Din_1);
  803. break;
  804. case 5:
  805. skip = digitalRead(Din_2);
  806. break;
  807. case 6:
  808. skip = digitalRead(Din_3);
  809. break;
  810. case 7:
  811. skip = digitalRead(Din_4);
  812. break;
  813. case 8:
  814. skip = !digitalRead(Din_1);
  815. break;
  816. case 9:
  817. skip = !digitalRead(Din_2);
  818. break;
  819. case 10:
  820. skip = !digitalRead(Din_3);
  821. break;
  822. case 11:
  823. skip = !digitalRead(Din_4);
  824. break;
  825. case 12:
  826. skip = !digitalRead(SW_PRG);
  827. break;
  828. case 13:
  829. skip = !digitalRead(SW_SEL);
  830. break;
  831. case 14:
  832. skip = digitalRead(SW_PRG);
  833. break;
  834. case 15:
  835. skip = digitalRead(SW_SEL);
  836. break;
  837. default:
  838. break;
  839. }
  840. if (skip) {
  841. addr += 1;
  842. }
  843. }
  844. /*
  845. calling a subroutine
  846. */
  847. void doCall(byte data) {
  848. saveaddr[saveCnt] = addr;
  849. saveCnt++;
  850. addr = page + data;
  851. }
  852. /*
  853. calling a subroutine, calling return and restart
  854. */
  855. void doCallSub(byte data) {
  856. if (data == 0) {
  857. if (saveCnt < 0) {
  858. doReset();
  859. return;
  860. }
  861. saveCnt -= 1;
  862. addr = saveaddr[saveCnt];
  863. dbgOut("r:");
  864. dbgOutLn(addr);
  865. return;
  866. }
  867. #ifdef SPS_ENHANCEMENT
  868. if (data <= 7) {
  869. // call subroutine number
  870. doCall(addr);
  871. addr = subs[data - 1];
  872. dbgOut("c:");
  873. dbgOutLn(addr);
  874. return;
  875. }
  876. if (data == 0x0f) {
  877. doReset();
  878. }
  879. #endif
  880. }
  881. /*
  882. calling a byte methods
  883. */
  884. void doByte(byte data) {
  885. #ifdef SPS_ENHANCEMENT
  886. dbgOut("B ");
  887. switch (data) {
  888. case 0:
  889. a = getAnalog(ADC_0);
  890. break;
  891. case 1:
  892. a = getAnalog(ADC_1);
  893. break;
  894. #ifdef SPS_RCRECEIVER
  895. case 2:
  896. tmpValue = pulseIn(RC_0, HIGH, 100000);
  897. if (tmpValue < 1000) {
  898. tmpValue = 1000;
  899. }
  900. if (tmpValue > 2000) {
  901. tmpValue = 2000;
  902. }
  903. a = (tmpValue - 1000) / 4; //(Umrechnen auf 4 bit)
  904. dbgOut("RC1:");
  905. dbgOut(tmpValue);
  906. dbgOut("=");
  907. dbgOutLn(a);
  908. break;
  909. case 3:
  910. tmpValue = pulseIn(RC_1, HIGH, 100000);
  911. if (tmpValue < 1000) {
  912. tmpValue = 1000;
  913. }
  914. if (tmpValue > 2000) {
  915. tmpValue = 2000;
  916. }
  917. a = (tmpValue - 1000) / 4; //(Umrechnen auf 4 bit)
  918. dbgOut("RC2:");
  919. dbgOut(tmpValue);
  920. dbgOut("=");
  921. dbgOutLn(a);
  922. break;
  923. #endif
  924. case 4:
  925. tmpValue = a;
  926. dbgOut("PWM1:");
  927. dbgOutLn(a);
  928. analogWrite(PWM_1, a);
  929. break;
  930. case 5:
  931. tmpValue = a;
  932. dbgOut("PWM2:");
  933. dbgOutLn(a);
  934. analogWrite(PWM_2, a);
  935. break;
  936. #ifdef SPS_SERVO
  937. case 6:
  938. if (servo1.attached()) {
  939. dbgOut("Srv1:");
  940. tmpValue = map(a, 0, 255, 0, 180);
  941. dbgOutLn(tmpValue);
  942. servo1.write(tmpValue);
  943. }
  944. break;
  945. case 7:
  946. if (servo2.attached()) {
  947. dbgOut("Srv2:");
  948. tmpValue = map(a, 0, 255, 0, 180);
  949. dbgOutLn(tmpValue);
  950. servo2.write(tmpValue);
  951. }
  952. break;
  953. #endif
  954. #ifdef SPS_TONE
  955. case 8:
  956. if (a == 0) {
  957. dbgOutLn("Tone off");
  958. noTone(PWM_2);
  959. } else {
  960. if (between(a, MIDI_START, MIDI_START + MIDI_NOTES)) {
  961. word frequenz = pgm_read_word(a - MIDI_START + midiNoteToFreq);
  962. dbgOut("Tone on: midi ");
  963. dbgOut2(a, DEC);
  964. dbgOut(", ");
  965. dbgOut2(frequenz, DEC);
  966. dbgOutLn("Hz");
  967. tone(PWM_2, frequenz);
  968. }
  969. }
  970. break;
  971. #endif
  972. #ifdef __AVR_ATmega328P__
  973. case 13:
  974. digitalWrite(LED_BUILTIN, 0);
  975. break;
  976. case 14:
  977. digitalWrite(LED_BUILTIN, 1);
  978. break;
  979. #endif
  980. }
  981. #endif
  982. }