1
0

SPS.ino 20 KB

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