usps.pas 30 KB

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