usps.pas 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327
  1. unit uSPS;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, MCSTools, uMicrobit;
  6. const
  7. CMD_NULL = $00;
  8. PORT = $10;
  9. DELAY = $20;
  10. JUMP_BACK = $30;
  11. SET_A = $40;
  12. IS_A = $50;
  13. A_IS = $60;
  14. CALC = $70;
  15. PAGE = $80;
  16. JUMP = $90;
  17. C_COUNT = $A0;
  18. D_COUNT = $B0;
  19. SKIP_IF = $C0;
  20. CALL = $D0;
  21. CALL_SUB = $E0;
  22. CMD_BYTE = $F0;
  23. const
  24. COMMANDS: array[0..15] of string =
  25. ('0', 'Dout', 'Delay', 'Jump -', 'A=#', '=A', 'A=',
  26. 'A=Calculation', 'Page', 'Jump', 'C*', 'D*', 'Skip if', 'Call', 'Ret', 'Byte/Board');
  27. O_LIST_H: array[0..15] of string =
  28. ('', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '');
  29. O_LIST_AT: array[0..15] of string =
  30. ('NOP', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '');
  31. O_LIST_MB: array[0..15] of string =
  32. ('NOP', 'SetPixel(x=A,y=B)', 'ClearPixel(x=A,y=B)', 'Image', '',
  33. '', '', '', '', '', '', '', '', '', '', '');
  34. DOUT_LIST: array[0..15] of string = ('Output 0000', 'Output 0001',
  35. 'Output 0010', 'Output 0011', 'Output 0100', 'Output 0101', 'Output 0110',
  36. 'Output 0111', 'Output 1000', 'Output 1001', 'Output 1010', 'Output 1011',
  37. 'Output 1100', 'Output 1101', 'Output 1110', 'Output 1111');
  38. DELAY_LIST: array[0..15] of string = ('Delay 1ms', 'Delay 2ms',
  39. 'Delay 5ms', 'Delay 10ms', 'Delay 20ms', 'Delay 50ms', 'Delay 100ms',
  40. 'Delay 200ms', 'Delay 500ms', 'Delay 1s', 'Delay 2s', 'Delay 5s',
  41. 'Delay 10s', 'Delay 20s', 'Delay 30s', 'Delay 60s');
  42. JUMP_B_LIST: array[0..15] of string = ('jump -0', 'jump -1',
  43. 'jump -2', 'jump -3', 'jump -4', 'jump -5', 'jump -6',
  44. 'jump -7', 'jump -8', 'jump -9', 'jump -10', 'jump -11',
  45. 'jump -12', 'jump -13', 'jump -14', 'jump -15');
  46. A_LIST: array[0..15] of string = ('A=0', 'A=1',
  47. 'A=2', 'A=3', 'A=4', 'A=5', 'A=6',
  48. 'A=7', 'A=8', 'A=9', 'A=10', 'A=11',
  49. 'A=12', 'A=13', 'A=14', 'A=15');
  50. IS_A_LIST_H: array[0..15] of string = ('', 'B=A',
  51. 'C=A', 'D=A', 'Dout=A', 'Dout.1=A.0', 'Dout.2=A.0',
  52. 'Dout.3=A.0', 'Dout.4=A.0', 'PWM.1=A', '', '',
  53. '', '', '', '');
  54. IS_A_LIST_A8: array[0..15] of string = ('', 'B=A',
  55. 'C=A', 'D=A', 'Dout=A', 'Dout.1=A.0', 'Dout.2=A.0',
  56. 'Dout.3=A.0', 'Dout.4=A.0', 'PWM.1=A', 'PWM.2=A', '',
  57. '', '', '', '');
  58. IS_A_LIST_AT: array[0..15] of string = ('A<->B', 'B=A',
  59. 'C=A', 'D=A', 'Dout=A', 'Dout.1=A.0', 'Dout.2=A.0',
  60. 'Dout.3=A.0', 'Dout.4=A.0', 'PWM.1=A', 'PWM.2=A', 'Servo.1=A',
  61. 'Servo.2=A', 'E=A', 'F=A', 'Push A');
  62. A_IS_LIST_H: array[0..15] of string = ('', 'A=B',
  63. 'A=C', 'A=D', 'A=Din', 'A=Din.1', 'A=Din.2',
  64. 'A=Din.3', 'A=Din.4', 'A=ADC.1', 'A=ADC.2', '',
  65. '', '', '', '');
  66. A_IS_LIST_A8: array[0..15] of string = ('', 'A=B',
  67. 'A=C', 'A=D', 'A=Din', 'A=Din.1', 'A=Din.2',
  68. 'A=Din.3', 'A=Din.4', 'A=ADC.1', 'A=ADC.2', '',
  69. '', '', '', '');
  70. A_IS_LIST_AT: array[0..15] of string = ('', 'A=B',
  71. 'A=C', 'A=D', 'A=Din', 'A=Din.1', 'A=Din.2',
  72. 'A=Din.3', 'A=Din.4', 'A=ADC.1', 'A=ADC.2', 'A=RC.1',
  73. 'A=RC.2', 'A=E', 'A=F', 'Pop A');
  74. A_CALC_LIST_H: array[0..15] of string = ('', 'A=A+1',
  75. 'A=A-1', 'A=A+B', 'A=A-B', 'A=A*B', 'A=A/B',
  76. 'A=A And B', 'A=A Or B', 'A=A Xor B', 'A=Not A', '',
  77. '', '', '', '');
  78. A_CALC_LIST_AT: array[0..15] of string = ('', 'A=A+1',
  79. 'A=A-1', 'A=A+B', 'A=A-B', 'A=A*B', 'A=A/B',
  80. 'A=A And B', 'A=A Or B', 'A=A Xor B', 'A=Not A', 'A=A % B',
  81. 'A=A+16*B', 'A = B - A', 'A=A SHR 1', 'A=A SHL 1');
  82. PAGE_LIST_H: array[0..15] of string = ('Page 0', 'Page 1',
  83. 'Page 2', 'Page 3', 'Page 4', 'Page 5', 'Page 6',
  84. 'Page 7', '', '', '', '', '', '', '', '');
  85. PAGE_LIST_AT: array[0..15] of string = ('Page 0', 'Page 1',
  86. 'Page 2', 'Page 3', 'Page 4', 'Page 5', 'Page 6',
  87. 'Page 7', 'Page 8', 'Page 9', 'Page A', 'Page B',
  88. 'Page C', 'Page D', 'Page E', 'Page F');
  89. JUMP_LIST: array[0..15] of string = ('Jump 0', 'Jump 1',
  90. 'Jump 2', 'Jump 3', 'Jump 4', 'Jump 5', 'Jump 6',
  91. 'Jump 7', 'Jump 8', 'Jump 9', 'Jump A', 'Jump B',
  92. 'Jump C', 'Jump D', 'Jump E', 'Jump F');
  93. C_LIST: array[0..15] of string = ('C 0', 'C 1',
  94. 'C 2', 'C 3', 'C 4', 'C 5', 'C 6',
  95. 'C 7', 'C 8', 'C 9', 'C A', 'C B',
  96. 'C C', 'C D', 'C E', 'C F');
  97. D_LIST: array[0..15] of string = ('D 0', 'D 1',
  98. 'D 2', 'D 3', 'D 4', 'D 5', 'D 6',
  99. 'D 7', 'D 8', 'D 9', 'D A', 'D B',
  100. 'D C', 'D D', 'D E', 'D F');
  101. SKIP_LIST_H: array[0..15] of string = ('', 'A>B',
  102. 'A<B', 'A=B', 'Din.1=1', 'Din.2=1', 'Din.3=1',
  103. 'Din.4=1', 'Din.1=0', 'Din.2=0', 'Din.3=0', 'Din.4=0',
  104. 'S_SEL=0', 'S_PRG=0', 'S_SEL=1', 'S_PRG=1');
  105. SKIP_LIST_A8: array[0..15] of string = ('', 'A>B',
  106. 'A<B', 'A=B', 'Din.1=1', 'Din.2=1', 'Din.3=1',
  107. 'Din.4=1', 'Din.1=0', 'Din.2=0', 'Din.3=0', 'Din.4=0',
  108. 'S_SEL=0', 'S_PRG=0', 'S_SEL=1', 'S_PRG=1');
  109. SKIP_LIST_AT: array[0..15] of string = ('A=0', 'A>B',
  110. 'A<B', 'A=B', 'Din.1=1', 'Din.2=1', 'Din.3=1',
  111. 'Din.4=1', 'Din.1=0', 'Din.2=0', 'Din.3=0', 'Din.4=0',
  112. 'S_SEL=0', 'S_PRG=0', 'S_SEL=1', 'S_PRG=1');
  113. CALL_LIST: array[0..15] of string = ('Jump 0', 'Jump 1',
  114. 'Jump 2', 'Jump 3', 'Jump 4', 'Jump 5', 'Jump 6',
  115. 'Jump 7', 'Jump 8', 'Jump 9', 'Jump A', 'Jump B',
  116. 'Jump C', 'Jump D', 'Jump E', 'Jump F');
  117. RET_LIST_H: array[0..15] of string = ('Return', '',
  118. '', '', '', '', '', '', '', '', '', '', '', '', '', '');
  119. RET_LIST_AT: array[0..15] of string = ('Return', 'Call 1',
  120. 'Call 2', 'Call 3', 'Call 4', 'Call 5', 'Call 6',
  121. '', 'Def 1', 'Def 2', 'Def 3', 'Def 4', 'Def 5',
  122. 'Def 6', '', 'Restart');
  123. F_LIST_H: array[0..15] of string =
  124. ('', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '');
  125. F_LIST_AT: array[0..15] of string = ('A=ADC.1', 'A=ADC.2', 'A=RCin.1', 'A=RCin.2',
  126. 'PWM.1=A', 'PWM.2=A', 'Servo.1=A', 'Servo.2=A', 'Tone=A', '', '', '',
  127. '', 'LED off', 'LED on', 'PrgEnd');
  128. F_LIST_MB: array[0..15] of string = ('A=ADC.1', 'A=ADC.2', 'A=RCin.1', 'A=RCin.2',
  129. 'PWM.1=A', 'PWM.2=A', 'Servo.1=A', 'Servo.2=A', 'Tone=A',
  130. 'A,E,F=Acc', 'A=Compass', 'A=Sound',
  131. 'A=Light', 'A=Logo', 'A=Gesture', 'PrgEnd');
  132. type
  133. {TPSVersion}
  134. TTPSVersion = (Holtek, ATMega8, ATTiny84, Arduino, Microbit, MicroBitV2);
  135. { TServo }
  136. TServo = class(TObject)
  137. private
  138. pinno: integer;
  139. myValue: byte;
  140. public
  141. constructor Create();
  142. procedure attach(pin: byte);
  143. function attached: boolean;
  144. function getValue: byte;
  145. procedure Write(Value: byte);
  146. end;
  147. { TDelayCallback }
  148. TDelayCallback = procedure(Value: integer);
  149. { TSPS }
  150. TSPS = class(TObject)
  151. private
  152. { private declarations }
  153. version: TTPSVersion;
  154. dout1, dout2, dout3, dout4: boolean;
  155. din1, din2, din3, din4: boolean;
  156. sw_prg, sw_sel: boolean;
  157. adc1, adc2: byte;
  158. pwm1, pwm2: byte;
  159. rc1, rc2: byte;
  160. subs: array[1..6] of word;
  161. saveaddr: array[0..15] of word;
  162. saveCnt: byte;
  163. eeprom: array[0..1024] of byte;
  164. e2e: word;
  165. adrPage: byte;
  166. addr: word;
  167. jumpAddr: word;
  168. a, b, c, d, e, f: byte;
  169. servo1, servo2: TServo;
  170. tone: integer;
  171. active: boolean;
  172. stop: boolean;
  173. stack: TByteStack;
  174. delayCallback: TDelayCallback;
  175. delayActive: boolean;
  176. // specials for microbit
  177. display: TMBImage;
  178. sw_logo: boolean;
  179. acc_x, acc_y, acc_z: byte;
  180. compass: byte;
  181. gesture: byte;
  182. soundLevel: byte;
  183. lightLevel: byte;
  184. errorMessage: string;
  185. procedure doNull(Data: byte);
  186. procedure doPort(Data: byte);
  187. procedure doDelay(Data: byte);
  188. procedure doJumpBack(Data: byte);
  189. procedure doSetA(Data: byte);
  190. procedure doAIs(Data: byte);
  191. procedure doIsA(Data: byte);
  192. procedure doCalc(Data: byte);
  193. procedure doPage(Data: byte);
  194. procedure doJump(Data: byte);
  195. procedure doCCount(Data: byte);
  196. procedure doDCount(Data: byte);
  197. procedure doSkipIf(Data: byte);
  198. procedure doCall(Data: byte);
  199. procedure doCallSub(Data: byte);
  200. procedure doByte(Data: byte);
  201. procedure doTone(Data: byte);
  202. procedure push(Data: byte);
  203. function pop(): byte;
  204. public
  205. { public declarations }
  206. constructor Create;
  207. destructor Destroy; override;
  208. procedure setDelayCallback(callback: TDelayCallback);
  209. function isDout1(): boolean;
  210. function isDout2(): boolean;
  211. function isDout3(): boolean;
  212. function isDout4(): boolean;
  213. function getPWM1(): byte;
  214. function getPWM2(): byte;
  215. function getServo1(): byte;
  216. function getServo2(): byte;
  217. function getTone(): integer;
  218. procedure setDin1(Data: boolean);
  219. procedure setDin2(Data: boolean);
  220. procedure setDin3(Data: boolean);
  221. procedure setDin4(Data: boolean);
  222. procedure setSPrg(Data: boolean);
  223. procedure setSSel(Data: boolean);
  224. procedure setADC1(Data: byte);
  225. procedure setADC2(Data: byte);
  226. procedure setRC1(Data: byte);
  227. procedure setRC2(Data: byte);
  228. // Microbit specials
  229. procedure setACC(x, y, z: byte);
  230. procedure setComp(Data: byte);
  231. procedure setGesture(Data: byte);
  232. procedure setLight(Data: byte);
  233. procedure setLogo(Data: boolean);
  234. procedure setSnd(Data: byte);
  235. function getDisplay(): TMBImage;
  236. // end
  237. procedure nextStep();
  238. procedure doReset();
  239. procedure start();
  240. procedure break();
  241. procedure doSingleCommand(command: byte);
  242. procedure preFetch();
  243. function getLastError():string;
  244. procedure writeEEProm(adr: byte; Data: byte);
  245. function isActive(): boolean;
  246. function isDelayActive(): boolean;
  247. function getAddress(): word;
  248. function getPage(): word;
  249. function getRAdr(): word;
  250. procedure getStack(List: TStrings);
  251. function getARegister(): byte;
  252. function getBRegister(): byte;
  253. function getCRegister(): byte;
  254. function getDRegister(): byte;
  255. function getERegister(): byte;
  256. function getFRegister(): byte;
  257. procedure setTPSVersion(tpsversion: TTPSVersion);
  258. procedure getCommands(list: TStrings);
  259. procedure getDatas(cmd: byte; list: TStrings);
  260. function getCommandText(cmd, Data: byte): string;
  261. function getJump(): byte;
  262. end;
  263. implementation
  264. uses Math, MCSStrings, LCLProc;
  265. { TServo }
  266. constructor TServo.Create;
  267. begin
  268. pinno := -1;
  269. end;
  270. procedure TServo.attach(pin: byte);
  271. begin
  272. pinno := pin;
  273. end;
  274. function TServo.attached: boolean;
  275. begin
  276. Result := pinno > -1;
  277. end;
  278. function TServo.getValue: byte;
  279. begin
  280. Result := myValue;
  281. end;
  282. procedure TServo.Write(Value: byte);
  283. begin
  284. myValue := Value;
  285. end;
  286. { TSPS }
  287. function TSPS.isDout1(): boolean;
  288. begin
  289. Result := dout1;
  290. end;
  291. function TSPS.isDout2(): boolean;
  292. begin
  293. Result := dout2;
  294. end;
  295. function TSPS.isDout3(): boolean;
  296. begin
  297. Result := dout3;
  298. end;
  299. function TSPS.isDout4(): boolean;
  300. begin
  301. Result := dout4;
  302. end;
  303. function TSPS.getPWM1(): byte;
  304. begin
  305. Result := pwm1;
  306. end;
  307. function TSPS.getPWM2(): byte;
  308. begin
  309. Result := pwm2;
  310. end;
  311. function TSPS.getServo1(): byte;
  312. begin
  313. Result := servo1.getValue;
  314. end;
  315. function TSPS.getServo2(): byte;
  316. begin
  317. Result := servo2.getValue;
  318. end;
  319. function TSPS.getTone(): integer;
  320. begin
  321. Result := tone;
  322. end;
  323. procedure TSPS.setDin1(Data: boolean);
  324. begin
  325. din1 := Data;
  326. end;
  327. procedure TSPS.setDin2(Data: boolean);
  328. begin
  329. din2 := Data;
  330. end;
  331. procedure TSPS.setDin3(Data: boolean);
  332. begin
  333. din3 := Data;
  334. end;
  335. procedure TSPS.setDin4(Data: boolean);
  336. begin
  337. din4 := Data;
  338. end;
  339. procedure TSPS.setSPrg(Data: boolean);
  340. begin
  341. sw_prg := Data;
  342. end;
  343. procedure TSPS.setSSel(Data: boolean);
  344. begin
  345. sw_sel := Data;
  346. end;
  347. procedure TSPS.setADC1(Data: byte);
  348. begin
  349. adc1 := Data;
  350. end;
  351. procedure TSPS.setADC2(Data: byte);
  352. begin
  353. adc2 := Data;
  354. end;
  355. procedure TSPS.setRC1(Data: byte);
  356. begin
  357. rc1 := Data;
  358. end;
  359. procedure TSPS.setRC2(Data: byte);
  360. begin
  361. rc2 := Data;
  362. end;
  363. procedure TSPS.nextStep();
  364. var
  365. Value: byte;
  366. oldAddr : word;
  367. begin
  368. errorMessage := '';
  369. Value := eeprom[addr];
  370. oldAddr := addr;
  371. addr := addr + 1;
  372. doSingleCommand(Value);
  373. if (addr > e2e) then
  374. begin
  375. errorMessage := 'Address out of range after address: 0x' + IntToHex(oldAddr, 2);
  376. doReset();
  377. end;
  378. preFetch();
  379. end;
  380. procedure TSPS.doReset();
  381. begin
  382. a := 0;
  383. b := 0;
  384. c := 0;
  385. d := 0;
  386. e := 0;
  387. f := 0;
  388. stack.Reset();
  389. active := False;
  390. din1 := False;
  391. din2 := False;
  392. din3 := False;
  393. din4 := False;
  394. dout1 := False;
  395. dout2 := False;
  396. dout3 := False;
  397. dout4 := False;
  398. addr := 0;
  399. adrPage := 0;
  400. pwm2 := 0;
  401. pwm1 := 0;
  402. adc1 := 0;
  403. adc2 := 0;
  404. saveCnt := 0;
  405. servo2.Write(0);
  406. servo1.Write(0);
  407. stop := False;
  408. sw_sel := False;
  409. acc_x := 0;
  410. acc_y := 0;
  411. acc_z := 0;
  412. compass := 0;
  413. gesture := 0;
  414. lightLevel := 0;
  415. soundLevel := 0;
  416. end;
  417. procedure TSPS.start();
  418. var
  419. Value, cmd, Data: byte;
  420. x: integer;
  421. begin
  422. doReset();
  423. for x := 0 to e2e do
  424. begin
  425. Value := eeprom[x];
  426. cmd := (Value and $F0);
  427. Data := (Value and $0F);
  428. if (cmd = CALL_SUB) then
  429. begin
  430. if (Data >= 8) then
  431. begin
  432. Data := Data - 7;
  433. subs[Data] := x + 1;
  434. end;
  435. end;
  436. if ((cmd = IS_A) and (Data = $0B)) then
  437. begin
  438. servo1.attach(0);
  439. end;
  440. if ((cmd = IS_A) and (Data = $0C)) then
  441. begin
  442. servo2.attach(1);
  443. end;
  444. if ((cmd = CMD_BYTE) and (Data = $06)) then
  445. begin
  446. servo1.attach(0);
  447. end;
  448. if ((cmd = CMD_BYTE) and (Data = $07)) then
  449. begin
  450. servo2.attach(1);
  451. end;
  452. end;
  453. active := True;
  454. end;
  455. procedure TSPS.break();
  456. begin
  457. stop := True;
  458. end;
  459. procedure TSPS.doSingleCommand(command: byte);
  460. var
  461. cmd, Data: byte;
  462. begin
  463. cmd := (command and $F0);
  464. Data := (command and $0F);
  465. case cmd of
  466. CMD_NULL: doNull(Data);
  467. PORT: doPort(Data);
  468. DELAY: doDelay(Data);
  469. JUMP_BACK: doJumpBack(Data);
  470. SET_A: doSetA(Data);
  471. A_IS: doAIs(Data);
  472. IS_A: doIsA(Data);
  473. CALC: doCalc(Data);
  474. PAGE: doPage(Data);
  475. JUMP: doJump(Data);
  476. C_COUNT: doCCount(Data);
  477. D_COUNT: doDCount(Data);
  478. SKIP_IF: doSkipIf(Data);
  479. CALL: doCall(Data);
  480. CALL_SUB: doCallSub(Data);
  481. CMD_BYTE: doByte(Data);
  482. end;
  483. end;
  484. procedure TSPS.preFetch();
  485. var
  486. cmd, Data: byte;
  487. skip: boolean;
  488. begin
  489. jumpAddr := 0;
  490. skip := False;
  491. cmd := eeprom[addr];
  492. Data := (cmd and $0F);
  493. cmd := (cmd and $F0);
  494. case cmd of
  495. C_COUNT:
  496. begin
  497. if (c > 0) then
  498. jumpAddr := Data + 16 * Page;
  499. end;
  500. D_COUNT:
  501. begin
  502. if (d > 0) then
  503. jumpAddr := Data + 16 * Page;
  504. end;
  505. JUMP_BACK: jumpAddr := addr - Data;
  506. JUMP: jumpAddr := Data + 16 * Page;
  507. SKIP_IF:
  508. begin
  509. case Data of
  510. 0: if (a = 0) then
  511. case version of
  512. ATTiny84, Arduino, Microbit, MicroBitV2: skip := True;
  513. end;
  514. 1: if (a > b) then
  515. skip := True;
  516. 2: if (a < b) then
  517. skip := True;
  518. 3: if (a = b) then
  519. skip := True;
  520. 4: if (din1) then
  521. skip := True;
  522. 5: if (din2) then
  523. skip := True;
  524. 6: if (din3) then
  525. skip := True;
  526. 7: if (din4) then
  527. skip := True;
  528. 8: if (not din1) then
  529. skip := True;
  530. 9: if (not din2) then
  531. skip := True;
  532. 10: if (not din3) then
  533. skip := True;
  534. 11: if (not din4) then
  535. skip := True;
  536. 12: if (sw_sel) then
  537. skip := True;
  538. 13: if (sw_prg) then
  539. skip := True;
  540. 14: if (not sw_sel) then
  541. skip := True;
  542. 15: if (not sw_prg) then
  543. skip := True;
  544. end;
  545. if (skip = True) then
  546. jumpAddr := addr + 2;
  547. end;
  548. end;
  549. end;
  550. function TSPS.getLastError(): string;
  551. begin
  552. result := errorMessage;
  553. end;
  554. procedure TSPS.writeEEProm(adr: byte; Data: byte);
  555. begin
  556. eeprom[adr] := Data;
  557. end;
  558. function TSPS.isActive(): boolean;
  559. begin
  560. Result := active;
  561. end;
  562. function TSPS.isDelayActive(): boolean;
  563. begin
  564. Result := delayActive;
  565. end;
  566. function TSPS.getAddress(): word;
  567. begin
  568. Result := addr;
  569. end;
  570. function TSPS.getPage(): word;
  571. begin
  572. Result := adrPage div 16;
  573. end;
  574. function TSPS.getRAdr(): word;
  575. begin
  576. if (saveCnt = 0) then
  577. begin
  578. Result := 0;
  579. end;
  580. Result := saveaddr[saveCnt - 1];
  581. end;
  582. procedure TSPS.getStack(List: TStrings);
  583. var
  584. i: integer;
  585. begin
  586. for i := 0 to stack.Count - 1 do
  587. begin
  588. List.Add(IntToHex(stack.peek(i), 2));
  589. end;
  590. end;
  591. function TSPS.getARegister(): byte;
  592. begin
  593. Result := a;
  594. end;
  595. function TSPS.getBRegister(): byte;
  596. begin
  597. Result := b;
  598. end;
  599. function TSPS.getCRegister(): byte;
  600. begin
  601. Result := c;
  602. end;
  603. function TSPS.getDRegister(): byte;
  604. begin
  605. Result := d;
  606. end;
  607. function TSPS.getERegister(): byte;
  608. begin
  609. Result := e;
  610. end;
  611. function TSPS.getFRegister(): byte;
  612. begin
  613. Result := f;
  614. end;
  615. procedure TSPS.setTPSVersion(tpsversion: TTPSVersion);
  616. begin
  617. version := tpsversion;
  618. case version of
  619. Holtek, ATMega8, ATTiny84, Microbit: e2e := 256;
  620. Arduino, MicroBitV2: e2e := 1024;
  621. end;
  622. end;
  623. procedure TSPS.getCommands(list: TStrings);
  624. begin
  625. MCSStrings.copyArray2List(COMMANDS, list);
  626. end;
  627. procedure TSPS.getDatas(cmd: byte; list: TStrings);
  628. begin
  629. if (cmd = 0) then
  630. begin
  631. case version of
  632. Holtek, ATMega8, Microbit: MCSStrings.copyArray2List(O_LIST_H, list);
  633. ATTiny84, Arduino: MCSStrings.copyArray2List(O_LIST_AT, list);
  634. MicroBitV2: MCSStrings.copyArray2List(O_LIST_MB, list);
  635. end;
  636. end;
  637. if (cmd = 1) then
  638. begin
  639. MCSStrings.copyArray2List(DOUT_LIST, list);
  640. end;
  641. if (cmd = 2) then
  642. MCSStrings.copyArray2List(DELAY_LIST, list);
  643. if (cmd = 3) then
  644. MCSStrings.copyArray2List(JUMP_B_LIST, list);
  645. if (cmd = 4) then
  646. MCSStrings.copyArray2List(A_LIST, list);
  647. if (cmd = 5) then
  648. begin
  649. case version of
  650. Holtek, Microbit: MCSStrings.copyArray2List(IS_A_LIST_H, list);
  651. ATMega8: MCSStrings.copyArray2List(IS_A_LIST_A8, list);
  652. ATTiny84, Arduino, MicroBitV2: MCSStrings.copyArray2List(IS_A_LIST_AT, list);
  653. end;
  654. end;
  655. if (cmd = 6) then
  656. begin
  657. case version of
  658. Holtek, Microbit: MCSStrings.copyArray2List(A_IS_LIST_H, list);
  659. ATMega8: MCSStrings.copyArray2List(A_IS_LIST_A8, list);
  660. ATTiny84, Arduino, MicroBitV2: MCSStrings.copyArray2List(A_IS_LIST_AT, list);
  661. end;
  662. end;
  663. if (cmd = 7) then
  664. begin
  665. case version of
  666. Holtek, ATMega8, Microbit: MCSStrings.copyArray2List(A_CALC_LIST_H, list);
  667. ATTiny84, Arduino, MicroBitV2: MCSStrings.copyArray2List(A_CALC_LIST_AT, list);
  668. end;
  669. end;
  670. if (cmd = 8) then
  671. begin
  672. case version of
  673. Holtek, ATMega8, Microbit: MCSStrings.copyArray2List(PAGE_LIST_H, list);
  674. ATTiny84, Arduino, MicroBitV2: MCSStrings.copyArray2List(PAGE_LIST_AT, list);
  675. end;
  676. end;
  677. if (cmd = 9) then
  678. MCSStrings.copyArray2List(JUMP_LIST, list);
  679. if (cmd = 10) then
  680. MCSStrings.copyArray2List(C_LIST, list);
  681. if (cmd = 11) then
  682. MCSStrings.copyArray2List(D_LIST, list);
  683. if (cmd = 12) then
  684. begin
  685. case version of
  686. Holtek, Microbit: MCSStrings.copyArray2List(SKIP_LIST_H, list);
  687. ATMega8: MCSStrings.copyArray2List(SKIP_LIST_A8, list);
  688. ATTiny84, Arduino, MicroBitV2: MCSStrings.copyArray2List(SKIP_LIST_AT, list);
  689. end;
  690. end;
  691. if (cmd = 13) then
  692. MCSStrings.copyArray2List(CALL_LIST, list);
  693. if (cmd = 14) then
  694. begin
  695. case version of
  696. Holtek, ATMega8, Microbit: MCSStrings.copyArray2List(RET_LIST_H, list);
  697. ATTiny84, Arduino, MicroBitV2: MCSStrings.copyArray2List(RET_LIST_AT, list);
  698. end;
  699. end;
  700. if (cmd = 15) then
  701. begin
  702. case version of
  703. Holtek, ATMega8, Microbit: MCSStrings.copyArray2List(F_LIST_H, list);
  704. ATTiny84, Arduino: MCSStrings.copyArray2List(F_LIST_AT, list);
  705. MicroBitV2: MCSStrings.copyArray2List(F_LIST_MB, list);
  706. end;
  707. end;
  708. end;
  709. function TSPS.getCommandText(cmd, Data: byte): string;
  710. var
  711. list: TStrings;
  712. line: string;
  713. begin
  714. if ((cmd >= 0) and (cmd < 16)) then
  715. begin
  716. list := TStringList.Create;
  717. getDatas(cmd, list);
  718. if ((Data >= 0) and (Data < 16)) then
  719. line := COMMANDS[cmd] + ':' + list[Data];
  720. list.Free;
  721. end;
  722. Result := line;
  723. end;
  724. function TSPS.getJump(): byte;
  725. begin
  726. Result := jumpAddr;
  727. end;
  728. procedure TSPS.doNull(Data: byte);
  729. var
  730. x, y: integer;
  731. image: TMBImage;
  732. begin
  733. // Do nothing
  734. if version = MicroBitV2 then
  735. begin
  736. case Data of
  737. 1: display[A, B] := 1;
  738. 2: display[A, B] := 0;
  739. 3:
  740. begin
  741. if A = 0 then
  742. begin
  743. for x := 0 to 4 do
  744. for y := 0 to 4 do
  745. display[x, y] := 0;
  746. end
  747. else
  748. begin
  749. image := IMAGE_MAP[4];
  750. if a <= length(IMAGE_MAP) then
  751. begin
  752. DebugLn('display an image');
  753. image := IMAGE_MAP[a];
  754. end;
  755. for x := 0 to 4 do
  756. for y := 0 to 4 do
  757. display[x, y] := image[x, y];
  758. end;
  759. end;
  760. end;
  761. end;
  762. end;
  763. // output to port
  764. procedure TSPS.doPort(Data: byte);
  765. begin
  766. dout1 := (Data and $01) > 0;
  767. dout2 := (Data and $02) > 0;
  768. dout3 := (Data and $04) > 0;
  769. dout4 := (Data and $08) > 0;
  770. end;
  771. // delay in ms
  772. procedure TSPS.doDelay(Data: byte);
  773. var
  774. delayValue: integer;
  775. x: integer;
  776. begin
  777. case Data of
  778. 0: delayValue := 1;
  779. 1: delayValue := 2;
  780. 2: delayValue := 5;
  781. 3: delayValue := 10;
  782. 4: delayValue := 20;
  783. 5: delayValue := 50;
  784. 6: delayValue := 100;
  785. 7: delayValue := 200;
  786. 8: delayValue := 500;
  787. 9: delayValue := 1000;
  788. 10: delayValue := 2000;
  789. 11: delayValue := 5000;
  790. 12: delayValue := 10000;
  791. 13: delayValue := 20000;
  792. 14: delayValue := 30000;
  793. 15: delayValue := 60000;
  794. end;
  795. delayActive := True;
  796. repeat
  797. if (delayValue >= 100) then
  798. begin
  799. Dec(delayValue, 100);
  800. Sleep(100);
  801. delayCallback(delayValue);
  802. end;
  803. until ((delayValue <= 100) or stop);
  804. delayCallback(0);
  805. delayActive := False;
  806. end;
  807. // jump relative back
  808. procedure TSPS.doJumpBack(Data: byte);
  809. begin
  810. addr := addr - Data - 1;
  811. end;
  812. // a = data
  813. procedure TSPS.doSetA(Data: byte);
  814. begin
  815. a := Data;
  816. end;
  817. // a = somthing;
  818. procedure TSPS.doAIs(Data: byte);
  819. begin
  820. case Data of
  821. 1: a := b;
  822. 2: a := c;
  823. 3: a := d;
  824. 4:
  825. begin
  826. a := 0;
  827. if (din1) then
  828. a := a + 1;
  829. if (din2) then
  830. a := a + 2;
  831. if (din3) then
  832. a := a + 4;
  833. if (din4) then
  834. a := a + 8;
  835. end;
  836. 5: if (din1) then
  837. a := 1
  838. else
  839. a := 0;
  840. 6: if (din2) then
  841. a := 1
  842. else
  843. a := 0;
  844. 7: if (din3) then
  845. a := 1
  846. else
  847. a := 0;
  848. 8: if (din4) then
  849. a := 1
  850. else
  851. a := 0;
  852. 9: a := adc1 and $0f; //(Umrechnen auf 4 bit)
  853. 10: a := adc2 and $0f; //(Umrechnen auf 4 bit)
  854. 11: a := rc1 and $0f; //(Umrechnen auf 4 bit)
  855. 12: a := rc2 and $0f; //(Umrechnen auf 4 bit)
  856. 13: a := e;
  857. 14: a := f;
  858. 15: a := pop();
  859. end;
  860. end;
  861. // somthing = a;
  862. procedure TSPS.doIsA(Data: byte);
  863. var
  864. tmpValue: byte;
  865. begin
  866. case Data of
  867. 0: case version of
  868. ATTiny84, Arduino, MicroBitV2:
  869. begin
  870. tmpValue := b;
  871. b := a;
  872. a := tmpValue;
  873. end;
  874. end;
  875. 1: b := a;
  876. 2: c := a;
  877. 3: d := a;
  878. 4: doPort(a);
  879. 5: dout1 := (a and $01) > 0;
  880. 6: dout2 := (a and $01) > 0;
  881. 7: dout3 := (a and $01) > 0;
  882. 8: dout4 := (a and $01) > 0;
  883. 9:
  884. begin
  885. pwm1 := a * 16;
  886. case version of
  887. Holtek:
  888. begin
  889. pwm1 := a;
  890. end;
  891. end;
  892. end;
  893. 10: pwm2 := a * 16;
  894. 11:
  895. begin
  896. if (servo1.attached()) then
  897. servo1.Write((a * 10) + 10);
  898. end;
  899. 12:
  900. begin
  901. if (servo2.attached()) then
  902. servo2.Write((a * 10) + 10);
  903. end;
  904. 13: e := a;
  905. 14: f := a;
  906. 15: push(a);
  907. end;
  908. end;
  909. // calculations
  910. procedure TSPS.doCalc(Data: byte);
  911. begin
  912. case Data of
  913. 1: a := a + 1;
  914. 2: a := a - 1;
  915. 3: a := a + b;
  916. 4: a := a - b;
  917. 5: a := a * b;
  918. 6: a := a div b;
  919. 7: a := a and b;
  920. 8: a := a or b;
  921. 9: a := a xor b;
  922. 10: a := not a;
  923. 11: case version of
  924. ATTiny84, Arduino, MicroBitV2: a := a mod b;
  925. end;
  926. 12: case version of
  927. ATTiny84, Arduino, MicroBitV2: a := a + 16 * b;
  928. end;
  929. 13: case version of
  930. ATTiny84, Arduino, MicroBitV2: a := b - a;
  931. end;
  932. 14: case version of
  933. ATTiny84, Arduino, MicroBitV2: a := a shr 1;
  934. end;
  935. 15: case version of
  936. ATTiny84, Arduino, MicroBitV2: a := a shl 1;
  937. end;
  938. end;
  939. case version of
  940. Holtek, ATMega8, Microbit: a := a and 15;
  941. end;
  942. end;
  943. // setting page
  944. procedure TSPS.doPage(Data: byte);
  945. begin
  946. adrPage := Data * 16;
  947. end;
  948. // jump absolute
  949. procedure TSPS.doJump(Data: byte);
  950. begin
  951. addr := adrPage + Data;
  952. end;
  953. // counting with c register
  954. procedure TSPS.doCCount(Data: byte);
  955. begin
  956. if (c > 0) then
  957. begin
  958. c := c - 1;
  959. c := c and $0F;
  960. doJump(Data);
  961. end;
  962. end;
  963. // counting with d register
  964. procedure TSPS.doDCount(Data: byte);
  965. begin
  966. if (d > 0) then
  967. begin
  968. d := d - 1;
  969. d := d and $0F;
  970. doJump(Data);
  971. end;
  972. end;
  973. // simple comdition = true skip next command
  974. procedure TSPS.doSkipIf(Data: byte);
  975. begin
  976. case (Data) of
  977. 0: if (a = 0) then
  978. case version of
  979. ATTiny84, Arduino, Microbit, MicroBitV2: addr := addr + 1;
  980. end;
  981. 1: if (a > b) then
  982. addr := addr + 1;
  983. 2: if (a < b) then
  984. addr := addr + 1;
  985. 3: if (a = b) then
  986. addr := addr + 1;
  987. 4: if (din1) then
  988. addr := addr + 1;
  989. 5: if (din2) then
  990. addr := addr + 1;
  991. 6: if (din3) then
  992. addr := addr + 1;
  993. 7: if (din4) then
  994. addr := addr + 1;
  995. 8: if (not din1) then
  996. addr := addr + 1;
  997. 9: if (not din2) then
  998. addr := addr + 1;
  999. 10: if (not din3) then
  1000. addr := addr + 1;
  1001. 11: if (not din4) then
  1002. addr := addr + 1;
  1003. 12: if (sw_sel) then
  1004. addr := addr + 1;
  1005. 13: if (sw_prg) then
  1006. addr := addr + 1;
  1007. 14: if (not sw_sel) then
  1008. addr := addr + 1;
  1009. 15: if (not sw_prg) then
  1010. addr := addr + 1;
  1011. end;
  1012. end;
  1013. // calling a subroutine
  1014. procedure TSPS.doCall(Data: byte);
  1015. begin
  1016. saveaddr[saveCnt] := addr;
  1017. case version of
  1018. ATTiny84, Arduino, MicroBitV2: saveCnt := saveCnt + 1;
  1019. end;
  1020. addr := adrpage + Data;
  1021. end;
  1022. // calling a subroutine, calling return and restart
  1023. procedure TSPS.doCallSub(Data: byte);
  1024. begin
  1025. if (Data = 0) then
  1026. begin
  1027. case version of
  1028. ATTiny84, Arduino, MicroBitV2:
  1029. begin
  1030. if (saveCnt = 0) then
  1031. begin
  1032. doReset();
  1033. exit;
  1034. end;
  1035. saveCnt := saveCnt - 1;
  1036. end;
  1037. end;
  1038. addr := saveaddr[saveCnt];
  1039. exit;
  1040. end;
  1041. if ((Data <= 6) and ((version = ATTiny84) or (version = Arduino) or (version = MicroBitV2))) then
  1042. begin
  1043. // call subroutine number
  1044. saveaddr[saveCnt] := addr;
  1045. saveCnt := saveCnt + 1;
  1046. addr := subs[Data];
  1047. exit;
  1048. end;
  1049. if ((Data = $0f) and ((version = ATTiny84) or (version = Arduino) or (version = MicroBitV2))) then
  1050. begin
  1051. doReset();
  1052. exit;
  1053. end;
  1054. end;
  1055. procedure TSPS.doByte(Data: byte);
  1056. var
  1057. Value: integer;
  1058. begin
  1059. // Some byte commands
  1060. case (Data) of
  1061. 0: case version of
  1062. ATTiny84, Arduino, MicroBitV2: a := adc1;
  1063. end;
  1064. 1: case version of
  1065. ATTiny84, Arduino, MicroBitV2: a := adc2;
  1066. end;
  1067. 2: case version of
  1068. ATTiny84, Arduino, MicroBitV2: a := rc1;
  1069. end;
  1070. 3: case version of
  1071. ATTiny84, Arduino, MicroBitV2: a := rc2;
  1072. end;
  1073. 4: pwm1 := a;
  1074. 5: pwm2 := a;
  1075. 6:
  1076. begin
  1077. if (servo1.attached()) then
  1078. begin
  1079. Value := (180 * a) div 255;
  1080. servo1.Write(Value);
  1081. end;
  1082. end;
  1083. 7:
  1084. begin
  1085. if (servo2.attached()) then
  1086. begin
  1087. Value := (180 * a) div 255;
  1088. servo2.Write(Value);
  1089. end;
  1090. end;
  1091. 8:
  1092. case version of
  1093. ATTiny84, Arduino, MicroBitV2: doTone(Data);
  1094. end;
  1095. 9:
  1096. case version of
  1097. MicroBitV2:
  1098. begin
  1099. a := acc_x;
  1100. e := acc_y;
  1101. f := acc_z;
  1102. end;
  1103. end;
  1104. 10:
  1105. case version of
  1106. MicroBitV2: a := compass;
  1107. end;
  1108. 11:
  1109. case version of
  1110. MicroBitV2: a := soundLevel;
  1111. end;
  1112. 12:
  1113. case version of
  1114. MicroBitV2: a := lightLevel;
  1115. end;
  1116. 13:
  1117. case version of
  1118. MicroBitV2: if sw_logo then
  1119. a := 1;
  1120. else
  1121. a := 0;
  1122. end;
  1123. 14:
  1124. case version of
  1125. MicroBitV2: a := gesture;
  1126. end;
  1127. 15:
  1128. begin
  1129. addr := 0;
  1130. exit;
  1131. end;
  1132. end;
  1133. end;
  1134. procedure TSPS.doTone(Data: byte);
  1135. begin
  1136. if (a in [36..109]) then
  1137. tone := a
  1138. else
  1139. tone := 0;
  1140. end;
  1141. procedure TSPS.setACC(x, y, z: byte);
  1142. begin
  1143. end;
  1144. procedure TSPS.setComp(Data: byte);
  1145. begin
  1146. end;
  1147. procedure TSPS.setSnd(Data: byte);
  1148. begin
  1149. end;
  1150. function TSPS.getDisplay(): TMBImage;
  1151. begin
  1152. Result := display;
  1153. end;
  1154. procedure TSPS.setLight(Data: byte);
  1155. begin
  1156. end;
  1157. procedure TSPS.setGesture(Data: byte);
  1158. begin
  1159. end;
  1160. procedure TSPS.setLogo(Data: boolean);
  1161. begin
  1162. end;
  1163. procedure TSPS.push(Data: byte);
  1164. begin
  1165. stack.Push(Data);
  1166. end;
  1167. function TSPS.pop(): byte;
  1168. begin
  1169. Result := stack.pop;
  1170. end;
  1171. constructor TSPS.Create;
  1172. begin
  1173. servo1 := TServo.Create();
  1174. servo2 := TServo.Create();
  1175. stack := TByteStack.Create;
  1176. stop := False;
  1177. delayActive := False;
  1178. end;
  1179. destructor TSPS.Destroy;
  1180. begin
  1181. inherited Destroy;
  1182. servo1.Free;
  1183. servo2.Free;
  1184. stack.Free;
  1185. end;
  1186. procedure TSPS.setDelayCallback(callback: TDelayCallback);
  1187. begin
  1188. delayCallback := callback;
  1189. end;
  1190. end.