usps.pas 30 KB

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