usps.pas 30 KB

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