usps.pas 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328
  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: word; 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: word; Data: byte);
  555. begin
  556. if adr < e2e then
  557. eeprom[adr] := Data;
  558. end;
  559. function TSPS.isActive(): boolean;
  560. begin
  561. Result := active;
  562. end;
  563. function TSPS.isDelayActive(): boolean;
  564. begin
  565. Result := delayActive;
  566. end;
  567. function TSPS.getAddress(): word;
  568. begin
  569. Result := addr;
  570. end;
  571. function TSPS.getPage(): word;
  572. begin
  573. Result := adrPage div 16;
  574. end;
  575. function TSPS.getRAdr(): word;
  576. begin
  577. if (saveCnt = 0) then
  578. begin
  579. Result := 0;
  580. end;
  581. Result := saveaddr[saveCnt - 1];
  582. end;
  583. procedure TSPS.getStack(List: TStrings);
  584. var
  585. i: integer;
  586. begin
  587. for i := 0 to stack.Count - 1 do
  588. begin
  589. List.Add(IntToHex(stack.peek(i), 2));
  590. end;
  591. end;
  592. function TSPS.getARegister(): byte;
  593. begin
  594. Result := a;
  595. end;
  596. function TSPS.getBRegister(): byte;
  597. begin
  598. Result := b;
  599. end;
  600. function TSPS.getCRegister(): byte;
  601. begin
  602. Result := c;
  603. end;
  604. function TSPS.getDRegister(): byte;
  605. begin
  606. Result := d;
  607. end;
  608. function TSPS.getERegister(): byte;
  609. begin
  610. Result := e;
  611. end;
  612. function TSPS.getFRegister(): byte;
  613. begin
  614. Result := f;
  615. end;
  616. procedure TSPS.setTPSVersion(tpsversion: TTPSVersion);
  617. begin
  618. version := tpsversion;
  619. case version of
  620. Holtek, ATMega8, ATTiny84, Microbit: e2e := 256;
  621. Arduino, MicroBitV2: e2e := 1024;
  622. end;
  623. end;
  624. procedure TSPS.getCommands(list: TStrings);
  625. begin
  626. MCSStrings.copyArray2List(COMMANDS, list);
  627. end;
  628. procedure TSPS.getDatas(cmd: byte; list: TStrings);
  629. begin
  630. if (cmd = 0) then
  631. begin
  632. case version of
  633. Holtek, ATMega8, Microbit: MCSStrings.copyArray2List(O_LIST_H, list);
  634. ATTiny84, Arduino: MCSStrings.copyArray2List(O_LIST_AT, list);
  635. MicroBitV2: MCSStrings.copyArray2List(O_LIST_MB, list);
  636. end;
  637. end;
  638. if (cmd = 1) then
  639. begin
  640. MCSStrings.copyArray2List(DOUT_LIST, list);
  641. end;
  642. if (cmd = 2) then
  643. MCSStrings.copyArray2List(DELAY_LIST, list);
  644. if (cmd = 3) then
  645. MCSStrings.copyArray2List(JUMP_B_LIST, list);
  646. if (cmd = 4) then
  647. MCSStrings.copyArray2List(A_LIST, list);
  648. if (cmd = 5) then
  649. begin
  650. case version of
  651. Holtek, Microbit: MCSStrings.copyArray2List(IS_A_LIST_H, list);
  652. ATMega8: MCSStrings.copyArray2List(IS_A_LIST_A8, list);
  653. ATTiny84, Arduino, MicroBitV2: MCSStrings.copyArray2List(IS_A_LIST_AT, list);
  654. end;
  655. end;
  656. if (cmd = 6) then
  657. begin
  658. case version of
  659. Holtek, Microbit: MCSStrings.copyArray2List(A_IS_LIST_H, list);
  660. ATMega8: MCSStrings.copyArray2List(A_IS_LIST_A8, list);
  661. ATTiny84, Arduino, MicroBitV2: MCSStrings.copyArray2List(A_IS_LIST_AT, list);
  662. end;
  663. end;
  664. if (cmd = 7) then
  665. begin
  666. case version of
  667. Holtek, ATMega8, Microbit: MCSStrings.copyArray2List(A_CALC_LIST_H, list);
  668. ATTiny84, Arduino, MicroBitV2: MCSStrings.copyArray2List(A_CALC_LIST_AT, list);
  669. end;
  670. end;
  671. if (cmd = 8) then
  672. begin
  673. case version of
  674. Holtek, ATMega8, Microbit: MCSStrings.copyArray2List(PAGE_LIST_H, list);
  675. ATTiny84, Arduino, MicroBitV2: MCSStrings.copyArray2List(PAGE_LIST_AT, list);
  676. end;
  677. end;
  678. if (cmd = 9) then
  679. MCSStrings.copyArray2List(JUMP_LIST, list);
  680. if (cmd = 10) then
  681. MCSStrings.copyArray2List(C_LIST, list);
  682. if (cmd = 11) then
  683. MCSStrings.copyArray2List(D_LIST, list);
  684. if (cmd = 12) then
  685. begin
  686. case version of
  687. Holtek, Microbit: MCSStrings.copyArray2List(SKIP_LIST_H, list);
  688. ATMega8: MCSStrings.copyArray2List(SKIP_LIST_A8, list);
  689. ATTiny84, Arduino, MicroBitV2: MCSStrings.copyArray2List(SKIP_LIST_AT, list);
  690. end;
  691. end;
  692. if (cmd = 13) then
  693. MCSStrings.copyArray2List(CALL_LIST, list);
  694. if (cmd = 14) then
  695. begin
  696. case version of
  697. Holtek, ATMega8, Microbit: MCSStrings.copyArray2List(RET_LIST_H, list);
  698. ATTiny84, Arduino, MicroBitV2: MCSStrings.copyArray2List(RET_LIST_AT, list);
  699. end;
  700. end;
  701. if (cmd = 15) then
  702. begin
  703. case version of
  704. Holtek, ATMega8, Microbit: MCSStrings.copyArray2List(F_LIST_H, list);
  705. ATTiny84, Arduino: MCSStrings.copyArray2List(F_LIST_AT, list);
  706. MicroBitV2: MCSStrings.copyArray2List(F_LIST_MB, list);
  707. end;
  708. end;
  709. end;
  710. function TSPS.getCommandText(cmd, Data: byte): string;
  711. var
  712. list: TStrings;
  713. line: string;
  714. begin
  715. if ((cmd >= 0) and (cmd < 16)) then
  716. begin
  717. list := TStringList.Create;
  718. getDatas(cmd, list);
  719. if ((Data >= 0) and (Data < 16)) then
  720. line := COMMANDS[cmd] + ':' + list[Data];
  721. list.Free;
  722. end;
  723. Result := line;
  724. end;
  725. function TSPS.getJump(): byte;
  726. begin
  727. Result := jumpAddr;
  728. end;
  729. procedure TSPS.doNull(Data: byte);
  730. var
  731. x, y: integer;
  732. image: TMBImage;
  733. begin
  734. // Do nothing
  735. if version = MicroBitV2 then
  736. begin
  737. case Data of
  738. 1: display[A, B] := 1;
  739. 2: display[A, B] := 0;
  740. 3:
  741. begin
  742. if A = 0 then
  743. begin
  744. for x := 0 to 4 do
  745. for y := 0 to 4 do
  746. display[x, y] := 0;
  747. end
  748. else
  749. begin
  750. image := IMAGE_MAP[4];
  751. if a <= length(IMAGE_MAP) then
  752. begin
  753. DebugLn('display an image');
  754. image := IMAGE_MAP[a];
  755. end;
  756. for x := 0 to 4 do
  757. for y := 0 to 4 do
  758. display[x, y] := image[x, y];
  759. end;
  760. end;
  761. end;
  762. end;
  763. end;
  764. // output to port
  765. procedure TSPS.doPort(Data: byte);
  766. begin
  767. dout1 := (Data and $01) > 0;
  768. dout2 := (Data and $02) > 0;
  769. dout3 := (Data and $04) > 0;
  770. dout4 := (Data and $08) > 0;
  771. end;
  772. // delay in ms
  773. procedure TSPS.doDelay(Data: byte);
  774. var
  775. delayValue: integer;
  776. x: integer;
  777. begin
  778. case Data of
  779. 0: delayValue := 1;
  780. 1: delayValue := 2;
  781. 2: delayValue := 5;
  782. 3: delayValue := 10;
  783. 4: delayValue := 20;
  784. 5: delayValue := 50;
  785. 6: delayValue := 100;
  786. 7: delayValue := 200;
  787. 8: delayValue := 500;
  788. 9: delayValue := 1000;
  789. 10: delayValue := 2000;
  790. 11: delayValue := 5000;
  791. 12: delayValue := 10000;
  792. 13: delayValue := 20000;
  793. 14: delayValue := 30000;
  794. 15: delayValue := 60000;
  795. end;
  796. delayActive := True;
  797. repeat
  798. if (delayValue >= 100) then
  799. begin
  800. Dec(delayValue, 100);
  801. Sleep(100);
  802. delayCallback(delayValue);
  803. end;
  804. until ((delayValue <= 100) or stop);
  805. delayCallback(0);
  806. delayActive := False;
  807. end;
  808. // jump relative back
  809. procedure TSPS.doJumpBack(Data: byte);
  810. begin
  811. addr := addr - Data - 1;
  812. end;
  813. // a = data
  814. procedure TSPS.doSetA(Data: byte);
  815. begin
  816. a := Data;
  817. end;
  818. // a = somthing;
  819. procedure TSPS.doAIs(Data: byte);
  820. begin
  821. case Data of
  822. 1: a := b;
  823. 2: a := c;
  824. 3: a := d;
  825. 4:
  826. begin
  827. a := 0;
  828. if (din1) then
  829. a := a + 1;
  830. if (din2) then
  831. a := a + 2;
  832. if (din3) then
  833. a := a + 4;
  834. if (din4) then
  835. a := a + 8;
  836. end;
  837. 5: if (din1) then
  838. a := 1
  839. else
  840. a := 0;
  841. 6: if (din2) then
  842. a := 1
  843. else
  844. a := 0;
  845. 7: if (din3) then
  846. a := 1
  847. else
  848. a := 0;
  849. 8: if (din4) then
  850. a := 1
  851. else
  852. a := 0;
  853. 9: a := adc1 and $0f; //(Umrechnen auf 4 bit)
  854. 10: a := adc2 and $0f; //(Umrechnen auf 4 bit)
  855. 11: a := rc1 and $0f; //(Umrechnen auf 4 bit)
  856. 12: a := rc2 and $0f; //(Umrechnen auf 4 bit)
  857. 13: a := e;
  858. 14: a := f;
  859. 15: a := pop();
  860. end;
  861. end;
  862. // somthing = a;
  863. procedure TSPS.doIsA(Data: byte);
  864. var
  865. tmpValue: byte;
  866. begin
  867. case Data of
  868. 0: case version of
  869. ATTiny84, Arduino, MicroBitV2:
  870. begin
  871. tmpValue := b;
  872. b := a;
  873. a := tmpValue;
  874. end;
  875. end;
  876. 1: b := a;
  877. 2: c := a;
  878. 3: d := a;
  879. 4: doPort(a);
  880. 5: dout1 := (a and $01) > 0;
  881. 6: dout2 := (a and $01) > 0;
  882. 7: dout3 := (a and $01) > 0;
  883. 8: dout4 := (a and $01) > 0;
  884. 9:
  885. begin
  886. pwm1 := a * 16;
  887. case version of
  888. Holtek:
  889. begin
  890. pwm1 := a;
  891. end;
  892. end;
  893. end;
  894. 10: pwm2 := a * 16;
  895. 11:
  896. begin
  897. if (servo1.attached()) then
  898. servo1.Write((a * 10) + 10);
  899. end;
  900. 12:
  901. begin
  902. if (servo2.attached()) then
  903. servo2.Write((a * 10) + 10);
  904. end;
  905. 13: e := a;
  906. 14: f := a;
  907. 15: push(a);
  908. end;
  909. end;
  910. // calculations
  911. procedure TSPS.doCalc(Data: byte);
  912. begin
  913. case Data of
  914. 1: a := a + 1;
  915. 2: a := a - 1;
  916. 3: a := a + b;
  917. 4: a := a - b;
  918. 5: a := a * b;
  919. 6: a := a div b;
  920. 7: a := a and b;
  921. 8: a := a or b;
  922. 9: a := a xor b;
  923. 10: a := not a;
  924. 11: case version of
  925. ATTiny84, Arduino, MicroBitV2: a := a mod b;
  926. end;
  927. 12: case version of
  928. ATTiny84, Arduino, MicroBitV2: a := a + 16 * b;
  929. end;
  930. 13: case version of
  931. ATTiny84, Arduino, MicroBitV2: a := b - a;
  932. end;
  933. 14: case version of
  934. ATTiny84, Arduino, MicroBitV2: a := a shr 1;
  935. end;
  936. 15: case version of
  937. ATTiny84, Arduino, MicroBitV2: a := a shl 1;
  938. end;
  939. end;
  940. case version of
  941. Holtek, ATMega8, Microbit: a := a and 15;
  942. end;
  943. end;
  944. // setting page
  945. procedure TSPS.doPage(Data: byte);
  946. begin
  947. adrPage := Data * 16;
  948. end;
  949. // jump absolute
  950. procedure TSPS.doJump(Data: byte);
  951. begin
  952. addr := adrPage + Data;
  953. end;
  954. // counting with c register
  955. procedure TSPS.doCCount(Data: byte);
  956. begin
  957. if (c > 0) then
  958. begin
  959. c := c - 1;
  960. c := c and $0F;
  961. doJump(Data);
  962. end;
  963. end;
  964. // counting with d register
  965. procedure TSPS.doDCount(Data: byte);
  966. begin
  967. if (d > 0) then
  968. begin
  969. d := d - 1;
  970. d := d and $0F;
  971. doJump(Data);
  972. end;
  973. end;
  974. // simple comdition = true skip next command
  975. procedure TSPS.doSkipIf(Data: byte);
  976. begin
  977. case (Data) of
  978. 0: if (a = 0) then
  979. case version of
  980. ATTiny84, Arduino, Microbit, MicroBitV2: addr := addr + 1;
  981. end;
  982. 1: if (a > b) then
  983. addr := addr + 1;
  984. 2: if (a < b) then
  985. addr := addr + 1;
  986. 3: if (a = b) then
  987. addr := addr + 1;
  988. 4: if (din1) then
  989. addr := addr + 1;
  990. 5: if (din2) then
  991. addr := addr + 1;
  992. 6: if (din3) then
  993. addr := addr + 1;
  994. 7: if (din4) then
  995. addr := addr + 1;
  996. 8: if (not din1) then
  997. addr := addr + 1;
  998. 9: if (not din2) then
  999. addr := addr + 1;
  1000. 10: if (not din3) then
  1001. addr := addr + 1;
  1002. 11: if (not din4) then
  1003. addr := addr + 1;
  1004. 12: if (sw_sel) then
  1005. addr := addr + 1;
  1006. 13: if (sw_prg) then
  1007. addr := addr + 1;
  1008. 14: if (not sw_sel) then
  1009. addr := addr + 1;
  1010. 15: if (not sw_prg) then
  1011. addr := addr + 1;
  1012. end;
  1013. end;
  1014. // calling a subroutine
  1015. procedure TSPS.doCall(Data: byte);
  1016. begin
  1017. saveaddr[saveCnt] := addr;
  1018. case version of
  1019. ATTiny84, Arduino, MicroBitV2: saveCnt := saveCnt + 1;
  1020. end;
  1021. addr := adrpage + Data;
  1022. end;
  1023. // calling a subroutine, calling return and restart
  1024. procedure TSPS.doCallSub(Data: byte);
  1025. begin
  1026. if (Data = 0) then
  1027. begin
  1028. case version of
  1029. ATTiny84, Arduino, MicroBitV2:
  1030. begin
  1031. if (saveCnt = 0) then
  1032. begin
  1033. doReset();
  1034. exit;
  1035. end;
  1036. saveCnt := saveCnt - 1;
  1037. end;
  1038. end;
  1039. addr := saveaddr[saveCnt];
  1040. exit;
  1041. end;
  1042. if ((Data <= 6) and ((version = ATTiny84) or (version = Arduino) or (version = MicroBitV2))) then
  1043. begin
  1044. // call subroutine number
  1045. saveaddr[saveCnt] := addr;
  1046. saveCnt := saveCnt + 1;
  1047. addr := subs[Data];
  1048. exit;
  1049. end;
  1050. if ((Data = $0f) and ((version = ATTiny84) or (version = Arduino) or (version = MicroBitV2))) then
  1051. begin
  1052. doReset();
  1053. exit;
  1054. end;
  1055. end;
  1056. procedure TSPS.doByte(Data: byte);
  1057. var
  1058. Value: integer;
  1059. begin
  1060. // Some byte commands
  1061. case (Data) of
  1062. 0: case version of
  1063. ATTiny84, Arduino, MicroBitV2: a := adc1;
  1064. end;
  1065. 1: case version of
  1066. ATTiny84, Arduino, MicroBitV2: a := adc2;
  1067. end;
  1068. 2: case version of
  1069. ATTiny84, Arduino, MicroBitV2: a := rc1;
  1070. end;
  1071. 3: case version of
  1072. ATTiny84, Arduino, MicroBitV2: a := rc2;
  1073. end;
  1074. 4: pwm1 := a;
  1075. 5: pwm2 := a;
  1076. 6:
  1077. begin
  1078. if (servo1.attached()) then
  1079. begin
  1080. Value := (180 * a) div 255;
  1081. servo1.Write(Value);
  1082. end;
  1083. end;
  1084. 7:
  1085. begin
  1086. if (servo2.attached()) then
  1087. begin
  1088. Value := (180 * a) div 255;
  1089. servo2.Write(Value);
  1090. end;
  1091. end;
  1092. 8:
  1093. case version of
  1094. ATTiny84, Arduino, MicroBitV2: doTone(Data);
  1095. end;
  1096. 9:
  1097. case version of
  1098. MicroBitV2:
  1099. begin
  1100. a := acc_x;
  1101. e := acc_y;
  1102. f := acc_z;
  1103. end;
  1104. end;
  1105. 10:
  1106. case version of
  1107. MicroBitV2: a := compass;
  1108. end;
  1109. 11:
  1110. case version of
  1111. MicroBitV2: a := soundLevel;
  1112. end;
  1113. 12:
  1114. case version of
  1115. MicroBitV2: a := lightLevel;
  1116. end;
  1117. 13:
  1118. case version of
  1119. MicroBitV2: if sw_logo then
  1120. a := 1;
  1121. else
  1122. a := 0;
  1123. end;
  1124. 14:
  1125. case version of
  1126. MicroBitV2: a := gesture;
  1127. end;
  1128. 15:
  1129. begin
  1130. addr := 0;
  1131. exit;
  1132. end;
  1133. end;
  1134. end;
  1135. procedure TSPS.doTone(Data: byte);
  1136. begin
  1137. if (a in [36..109]) then
  1138. tone := a
  1139. else
  1140. tone := 0;
  1141. end;
  1142. procedure TSPS.setACC(x, y, z: byte);
  1143. begin
  1144. end;
  1145. procedure TSPS.setComp(Data: byte);
  1146. begin
  1147. end;
  1148. procedure TSPS.setSnd(Data: byte);
  1149. begin
  1150. end;
  1151. function TSPS.getDisplay(): TMBImage;
  1152. begin
  1153. Result := display;
  1154. end;
  1155. procedure TSPS.setLight(Data: byte);
  1156. begin
  1157. end;
  1158. procedure TSPS.setGesture(Data: byte);
  1159. begin
  1160. end;
  1161. procedure TSPS.setLogo(Data: boolean);
  1162. begin
  1163. end;
  1164. procedure TSPS.push(Data: byte);
  1165. begin
  1166. stack.Push(Data);
  1167. end;
  1168. function TSPS.pop(): byte;
  1169. begin
  1170. Result := stack.pop;
  1171. end;
  1172. constructor TSPS.Create;
  1173. begin
  1174. servo1 := TServo.Create();
  1175. servo2 := TServo.Create();
  1176. stack := TByteStack.Create;
  1177. stop := False;
  1178. delayActive := False;
  1179. end;
  1180. destructor TSPS.Destroy;
  1181. begin
  1182. inherited Destroy;
  1183. servo1.Free;
  1184. servo2.Free;
  1185. stack.Free;
  1186. end;
  1187. procedure TSPS.setDelayCallback(callback: TDelayCallback);
  1188. begin
  1189. delayCallback := callback;
  1190. end;
  1191. end.