usps.pas 31 KB

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