usps.pas 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170
  1. unit uSPS;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, MCSTools;
  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');
  27. O_LIST_H: array[0..15] of string =
  28. ('', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '');
  29. O_LIST_AT: array[0..15] of string =
  30. ('NOP', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '');
  31. DOUT_LIST: array[0..15] of string = ('Output 0000', 'Output 0001',
  32. 'Output 0010', 'Output 0011', 'Output 0100', 'Output 0101', 'Output 0110',
  33. 'Output 0111', 'Output 1000', 'Output 1001', 'Output 1010', 'Output 1011',
  34. 'Output 1100', 'Output 1101', 'Output 1110', 'Output 1111');
  35. DELAY_LIST: array[0..15] of string = ('Delay 1ms', 'Delay 2ms',
  36. 'Delay 5ms', 'Delay 10ms', 'Delay 20ms', 'Delay 50ms', 'Delay 100ms',
  37. 'Delay 200ms', 'Delay 500ms', 'Delay 1s', 'Delay 2s', 'Delay 5s',
  38. 'Delay 10s', 'Delay 20s', 'Delay 30s', 'Delay 60s');
  39. JUMP_B_LIST: array[0..15] of string = ('jump -0', 'jump -1',
  40. 'jump -2', 'jump -3', 'jump -4', 'jump -5', 'jump -6',
  41. 'jump -7', 'jump -8', 'jump -9', 'jump -10', 'jump -11',
  42. 'jump -12', 'jump -13', 'jump -14', 'jump -15');
  43. A_LIST: array[0..15] of string = ('A=0', 'A=1',
  44. 'A=2', 'A=3', 'A=4', 'A=5', 'A=6',
  45. 'A=7', 'A=8', 'A=9', 'A=10', 'A=11',
  46. 'A=12', 'A=13', 'A=14', 'A=15');
  47. IS_A_LIST_H: array[0..15] of string = ('', 'B=A',
  48. 'C=A', 'D=A', 'Dout=A', 'Dout.1=A.0', 'Dout.2=A.0',
  49. 'Dout.3=A.0', 'Dout.4=A.0', 'PWM.1=A', '', '',
  50. '', '', '', '');
  51. IS_A_LIST_A8: array[0..15] of string = ('', 'B=A',
  52. 'C=A', 'D=A', 'Dout=A', 'Dout.1=A.0', 'Dout.2=A.0',
  53. 'Dout.3=A.0', 'Dout.4=A.0', 'PWM.1=A', 'PWM.2=A', '',
  54. '', '', '', '');
  55. IS_A_LIST_AT: array[0..15] of string = ('A<->B', 'B=A',
  56. 'C=A', 'D=A', 'Dout=A', 'Dout.1=A.0', 'Dout.2=A.0',
  57. 'Dout.3=A.0', 'Dout.4=A.0', 'PWM.1=A', 'PWM.2=A', 'Servo.1=A',
  58. 'Servo.2=A', 'E=A', 'F=A', 'Push A');
  59. A_IS_LIST_H: array[0..15] of string = ('', 'A=B',
  60. 'A=C', 'A=D', 'A=Din', 'A=Din.1', 'A=Din.2',
  61. 'A=Din.3', 'A=Din.4', 'A=ADC.1', 'A=ADC.2', '',
  62. '', '', '', '');
  63. A_IS_LIST_A8: array[0..15] of string = ('', 'A=B',
  64. 'A=C', 'A=D', 'A=Din', 'A=Din.1', 'A=Din.2',
  65. 'A=Din.3', 'A=Din.4', 'A=ADC.1', 'A=ADC.2', '',
  66. '', '', '', '');
  67. A_IS_LIST_AT: array[0..15] of string = ('', 'A=B',
  68. 'A=C', 'A=D', 'A=Din', 'A=Din.1', 'A=Din.2',
  69. 'A=Din.3', 'A=Din.4', 'A=ADC.1', 'A=ADC.2', 'A=RC.1',
  70. 'A=RC.2', 'A=E', 'A=F', 'Pop A');
  71. A_CALC_LIST_H: array[0..15] of string = ('', 'A=A+1',
  72. 'A=A-1', 'A=A+B', 'A=A-B', 'A=A*B', 'A=A/B',
  73. 'A=A And B', 'A=A Or B', 'A=A Xor B', 'A=Not A', '',
  74. '', '', '', '');
  75. A_CALC_LIST_AT: array[0..15] of string = ('', 'A=A+1',
  76. 'A=A-1', 'A=A+B', 'A=A-B', 'A=A*B', 'A=A/B',
  77. 'A=A And B', 'A=A Or B', 'A=A Xor B', 'A=Not A', 'A=A % B',
  78. 'A=A+16*B', 'A = B - A', 'A=A SHR 1', 'A=A SHL 1');
  79. PAGE_LIST_H: array[0..15] of string = ('Page 0', 'Page 1',
  80. 'Page 2', 'Page 3', 'Page 4', 'Page 5', 'Page 6',
  81. 'Page 7', '', '', '', '', '', '', '', '');
  82. PAGE_LIST_AT: array[0..15] of string = ('Page 0', 'Page 1',
  83. 'Page 2', 'Page 3', 'Page 4', 'Page 5', 'Page 6',
  84. 'Page 7', 'Page 8', 'Page 9', 'Page A', 'Page B',
  85. 'Page C', 'Page D', 'Page E', 'Page F');
  86. JUMP_LIST: array[0..15] of string = ('Jump 0', 'Jump 1',
  87. 'Jump 2', 'Jump 3', 'Jump 4', 'Jump 5', 'Jump 6',
  88. 'Jump 7', 'Jump 8', 'Jump 9', 'Jump A', 'Jump B',
  89. 'Jump C', 'Jump D', 'Jump E', 'Jump F');
  90. C_LIST: array[0..15] of string = ('C 0', 'C 1',
  91. 'C 2', 'C 3', 'C 4', 'C 5', 'C 6',
  92. 'C 7', 'C 8', 'C 9', 'C A', 'C B',
  93. 'C C', 'C D', 'C E', 'C F');
  94. D_LIST: array[0..15] of string = ('D 0', 'D 1',
  95. 'D 2', 'D 3', 'D 4', 'D 5', 'D 6',
  96. 'D 7', 'D 8', 'D 9', 'D A', 'D B',
  97. 'D C', 'D D', 'D E', 'D F');
  98. SKIP_LIST_H: array[0..15] of string = ('', 'A>B',
  99. 'A<B', 'A=B', 'Din.1=1', 'Din.2=1', 'Din.3=1',
  100. 'Din.4=1', 'Din.1=0', 'Din.2=0', 'Din.3=0', 'Din.4=0',
  101. 'S_SEL=0', 'S_PRG=0', 'S_SEL=1', 'S_PRG=1');
  102. SKIP_LIST_A8: array[0..15] of string = ('', 'A>B',
  103. 'A<B', 'A=B', 'Din.1=1', 'Din.2=1', 'Din.3=1',
  104. 'Din.4=1', 'Din.1=0', 'Din.2=0', 'Din.3=0', 'Din.4=0',
  105. 'S_SEL=0', 'S_PRG=0', 'S_SEL=1', 'S_PRG=1');
  106. SKIP_LIST_AT: array[0..15] of string = ('A=0', 'A>B',
  107. 'A<B', 'A=B', 'Din.1=1', 'Din.2=1', 'Din.3=1',
  108. 'Din.4=1', 'Din.1=0', 'Din.2=0', 'Din.3=0', 'Din.4=0',
  109. 'S_SEL=0', 'S_PRG=0', 'S_SEL=1', 'S_PRG=1');
  110. CALL_LIST: array[0..15] of string = ('Jump 0', 'Jump 1',
  111. 'Jump 2', 'Jump 3', 'Jump 4', 'Jump 5', 'Jump 6',
  112. 'Jump 7', 'Jump 8', 'Jump 9', 'Jump A', 'Jump B',
  113. 'Jump C', 'Jump D', 'Jump E', 'Jump F');
  114. RET_LIST_H: array[0..15] of string = ('Return', '',
  115. '', '', '', '', '', '', '', '', '', '', '', '', '', '');
  116. RET_LIST_AT: array[0..15] of string = ('Return', 'Call 1',
  117. 'Call 2', 'Call 3', 'Call 4', 'Call 5', 'Call 6',
  118. '', 'Def 1', 'Def 2', 'Def 3', 'Def 4', 'Def 5',
  119. 'Def 6', '', 'Restart');
  120. F_LIST_H: array[0..15] of string =
  121. ('', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '');
  122. F_LIST_AT: array[0..15] of string = ('A=ADC.1', 'A=ADC.2', 'A=RCin.1', 'A=RCin.2',
  123. 'PWM.1=A', 'PWM.2=A', 'Servo.1=A', 'Servo.2=A', 'Tone=A', '', '', '',
  124. '', 'LED off', 'LED on', 'PrgEnd');
  125. type
  126. {TPSVersion}
  127. TTPSVersion = (Holtek, ATMega8, ATTiny84, Arduino);
  128. { TServo }
  129. TServo = class(TObject)
  130. private
  131. pinno: integer;
  132. myValue: byte;
  133. public
  134. constructor Create();
  135. procedure attach(pin: byte);
  136. function attached: boolean;
  137. function getValue: byte;
  138. procedure Write(Value: byte);
  139. end;
  140. { TDelayCallback }
  141. TDelayCallback = procedure(Value: integer);
  142. { TSPS }
  143. TSPS = class(TObject)
  144. private
  145. { private declarations }
  146. version: TTPSVersion;
  147. dout1, dout2, dout3, dout4: boolean;
  148. din1, din2, din3, din4: boolean;
  149. sw_prg, sw_sel: boolean;
  150. adc1, adc2: byte;
  151. pwm1, pwm2: byte;
  152. rc1, rc2: byte;
  153. subs: array[1..6] of word;
  154. saveaddr: array[0..15] of word;
  155. saveCnt: byte;
  156. eeprom: array[0..255] of byte;
  157. adrPage: byte;
  158. addr: word;
  159. jumpAddr: word;
  160. a, b, c, d, e, f: byte;
  161. servo1, servo2: TServo;
  162. tone: integer;
  163. active: boolean;
  164. stop: boolean;
  165. stack: TByteStack;
  166. delayCallback: TDelayCallback;
  167. delayActive: boolean;
  168. procedure doNull(Data: byte);
  169. procedure doPort(Data: byte);
  170. procedure doDelay(Data: byte);
  171. procedure doJumpBack(Data: byte);
  172. procedure doSetA(Data: byte);
  173. procedure doAIs(Data: byte);
  174. procedure doIsA(Data: byte);
  175. procedure doCalc(Data: byte);
  176. procedure doPage(Data: byte);
  177. procedure doJump(Data: byte);
  178. procedure doCCount(Data: byte);
  179. procedure doDCount(Data: byte);
  180. procedure doSkipIf(Data: byte);
  181. procedure doCall(Data: byte);
  182. procedure doCallSub(Data: byte);
  183. procedure doByte(Data: byte);
  184. procedure doTone(Data: byte);
  185. procedure push(Data: byte);
  186. function pop(): byte;
  187. public
  188. { public declarations }
  189. constructor Create;
  190. destructor Destroy; override;
  191. procedure setDelayCallback(callback: TDelayCallback);
  192. function isDout1(): boolean;
  193. function isDout2(): boolean;
  194. function isDout3(): boolean;
  195. function isDout4(): boolean;
  196. function getPWM1(): byte;
  197. function getPWM2(): byte;
  198. function getServo1(): byte;
  199. function getServo2(): byte;
  200. function getTone(): integer;
  201. procedure setDin1(Data: boolean);
  202. procedure setDin2(Data: boolean);
  203. procedure setDin3(Data: boolean);
  204. procedure setDin4(Data: boolean);
  205. procedure setSPrg(Data: boolean);
  206. procedure setSSel(Data: boolean);
  207. procedure setADC1(Data: byte);
  208. procedure setADC2(Data: byte);
  209. procedure setRC1(Data: byte);
  210. procedure setRC2(Data: byte);
  211. procedure nextStep();
  212. procedure doReset();
  213. procedure start();
  214. procedure break();
  215. procedure doSingleCommand(command: byte);
  216. procedure preFetch();
  217. procedure writeEEProm(adr: byte; Data: byte);
  218. function isActive(): boolean;
  219. function isDelayActive(): boolean;
  220. function getAddress(): word;
  221. function getPage(): word;
  222. function getRAdr(): word;
  223. procedure getStack(List: TStrings);
  224. function getARegister(): byte;
  225. function getBRegister(): byte;
  226. function getCRegister(): byte;
  227. function getDRegister(): byte;
  228. function getERegister(): byte;
  229. function getFRegister(): byte;
  230. procedure setTPSVersion(tpsversion: TTPSVersion);
  231. procedure getCommands(list: TStrings);
  232. procedure getDatas(cmd: byte; list: TStrings);
  233. function getCommandText(cmd, Data: byte): string;
  234. function getJump(): byte;
  235. end;
  236. implementation
  237. uses Math, MCSStrings;
  238. { TServo }
  239. constructor TServo.Create;
  240. begin
  241. pinno := -1;
  242. end;
  243. procedure TServo.attach(pin: byte);
  244. begin
  245. pinno := pin;
  246. end;
  247. function TServo.attached: boolean;
  248. begin
  249. Result := pinno > -1;
  250. end;
  251. function TServo.getValue: byte;
  252. begin
  253. Result := myValue;
  254. end;
  255. procedure TServo.Write(Value: byte);
  256. begin
  257. myValue := Value;
  258. end;
  259. { TSPS }
  260. function TSPS.isDout1(): boolean;
  261. begin
  262. Result := dout1;
  263. end;
  264. function TSPS.isDout2(): boolean;
  265. begin
  266. Result := dout2;
  267. end;
  268. function TSPS.isDout3(): boolean;
  269. begin
  270. Result := dout3;
  271. end;
  272. function TSPS.isDout4(): boolean;
  273. begin
  274. Result := dout4;
  275. end;
  276. function TSPS.getPWM1(): byte;
  277. begin
  278. Result := pwm1;
  279. end;
  280. function TSPS.getPWM2(): byte;
  281. begin
  282. Result := pwm2;
  283. end;
  284. function TSPS.getServo1(): byte;
  285. begin
  286. Result := servo1.getValue;
  287. end;
  288. function TSPS.getServo2(): byte;
  289. begin
  290. Result := servo2.getValue;
  291. end;
  292. function TSPS.getTone(): integer;
  293. begin
  294. Result := tone;
  295. end;
  296. procedure TSPS.setDin1(Data: boolean);
  297. begin
  298. din1 := Data;
  299. end;
  300. procedure TSPS.setDin2(Data: boolean);
  301. begin
  302. din2 := Data;
  303. end;
  304. procedure TSPS.setDin3(Data: boolean);
  305. begin
  306. din3 := Data;
  307. end;
  308. procedure TSPS.setDin4(Data: boolean);
  309. begin
  310. din4 := Data;
  311. end;
  312. procedure TSPS.setSPrg(Data: boolean);
  313. begin
  314. sw_prg := Data;
  315. end;
  316. procedure TSPS.setSSel(Data: boolean);
  317. begin
  318. sw_sel := Data;
  319. end;
  320. procedure TSPS.setADC1(Data: byte);
  321. begin
  322. adc1 := Data;
  323. end;
  324. procedure TSPS.setADC2(Data: byte);
  325. begin
  326. adc2 := Data;
  327. end;
  328. procedure TSPS.setRC1(Data: byte);
  329. begin
  330. rc1 := Data;
  331. end;
  332. procedure TSPS.setRC2(Data: byte);
  333. begin
  334. rc2 := Data;
  335. end;
  336. procedure TSPS.nextStep();
  337. var
  338. Value: byte;
  339. begin
  340. Value := eeprom[addr];
  341. addr := addr + 1;
  342. doSingleCommand(Value);
  343. if (addr > SizeOf(eeprom)) then
  344. begin
  345. doReset();
  346. end;
  347. preFetch();
  348. end;
  349. procedure TSPS.doReset();
  350. begin
  351. a := 0;
  352. b := 0;
  353. c := 0;
  354. d := 0;
  355. e := 0;
  356. f := 0;
  357. stack.Reset();
  358. active := False;
  359. din1 := False;
  360. din2 := False;
  361. din3 := False;
  362. din4 := False;
  363. dout1 := False;
  364. dout2 := False;
  365. dout3 := False;
  366. dout4 := False;
  367. addr := 0;
  368. adrPage := 0;
  369. pwm2 := 0;
  370. pwm1 := 0;
  371. adc1 := 0;
  372. adc2 := 0;
  373. saveCnt := 0;
  374. servo2.Write(0);
  375. servo1.Write(0);
  376. stop := False;
  377. end;
  378. procedure TSPS.start();
  379. var
  380. Value, cmd, Data: byte;
  381. x: integer;
  382. begin
  383. doReset();
  384. for x := 0 to SizeOf(eeprom) do
  385. begin
  386. Value := eeprom[x];
  387. cmd := (Value and $F0);
  388. Data := (Value and $0F);
  389. if (cmd = CALL_SUB) then
  390. begin
  391. if (Data >= 8) then
  392. begin
  393. Data := Data - 7;
  394. subs[Data] := x + 1;
  395. end;
  396. end;
  397. if ((cmd = IS_A) and (Data = $0B)) then
  398. begin
  399. servo1.attach(0);
  400. end;
  401. if ((cmd = IS_A) and (Data = $0C)) then
  402. begin
  403. servo2.attach(1);
  404. end;
  405. if ((cmd = CMD_BYTE) and (Data = $06)) then
  406. begin
  407. servo1.attach(0);
  408. end;
  409. if ((cmd = CMD_BYTE) and (Data = $07)) then
  410. begin
  411. servo2.attach(1);
  412. end;
  413. end;
  414. active := True;
  415. end;
  416. procedure TSPS.break();
  417. begin
  418. stop := True;
  419. end;
  420. procedure TSPS.doSingleCommand(command: byte);
  421. var
  422. cmd, Data: byte;
  423. begin
  424. cmd := (command and $F0);
  425. Data := (command and $0F);
  426. case cmd of
  427. CMD_NULL: doNull(Data);
  428. PORT: doPort(Data);
  429. DELAY: doDelay(Data);
  430. JUMP_BACK: doJumpBack(Data);
  431. SET_A: doSetA(Data);
  432. A_IS: doAIs(Data);
  433. IS_A: doIsA(Data);
  434. CALC: doCalc(Data);
  435. PAGE: doPage(Data);
  436. JUMP: doJump(Data);
  437. C_COUNT: doCCount(Data);
  438. D_COUNT: doDCount(Data);
  439. SKIP_IF: doSkipIf(Data);
  440. CALL: doCall(Data);
  441. CALL_SUB: doCallSub(Data);
  442. CMD_BYTE: doByte(Data);
  443. end;
  444. end;
  445. procedure TSPS.preFetch();
  446. var
  447. cmd, Data: byte;
  448. skip: boolean;
  449. begin
  450. jumpAddr := 0;
  451. skip := False;
  452. cmd := eeprom[addr];
  453. Data := (cmd and $0F);
  454. cmd := (cmd and $F0);
  455. case cmd of
  456. C_COUNT:
  457. begin
  458. if (c > 0) then
  459. jumpAddr := Data + 16 * Page;
  460. end;
  461. D_COUNT:
  462. begin
  463. if (d > 0) then
  464. jumpAddr := Data + 16 * Page;
  465. end;
  466. JUMP_BACK: jumpAddr := addr - Data;
  467. JUMP: jumpAddr := Data + 16 * Page;
  468. SKIP_IF:
  469. begin
  470. case Data of
  471. 0: if (a = 0) then
  472. case version of
  473. ATTiny84, Arduino: skip := True;
  474. end;
  475. 1: if (a > b) then
  476. skip := True;
  477. 2: if (a < b) then
  478. skip := True;
  479. 3: if (a = b) then
  480. skip := True;
  481. 4: if (din1) then
  482. skip := True;
  483. 5: if (din2) then
  484. skip := True;
  485. 6: if (din3) then
  486. skip := True;
  487. 7: if (din4) then
  488. skip := True;
  489. 8: if (not din1) then
  490. skip := True;
  491. 9: if (not din2) then
  492. skip := True;
  493. 10: if (not din3) then
  494. skip := True;
  495. 11: if (not din4) then
  496. skip := True;
  497. 12: if (sw_sel) then
  498. skip := True;
  499. 13: if (sw_prg) then
  500. skip := True;
  501. 14: if (not sw_sel) then
  502. skip := True;
  503. 15: if (not sw_prg) then
  504. skip := True;
  505. end;
  506. if (skip = True) then
  507. jumpAddr := addr + 2;
  508. end;
  509. end;
  510. end;
  511. procedure TSPS.writeEEProm(adr: byte; Data: byte);
  512. begin
  513. eeprom[adr] := Data;
  514. end;
  515. function TSPS.isActive(): boolean;
  516. begin
  517. Result := active;
  518. end;
  519. function TSPS.isDelayActive(): boolean;
  520. begin
  521. Result := delayActive;
  522. end;
  523. function TSPS.getAddress(): word;
  524. begin
  525. Result := addr;
  526. end;
  527. function TSPS.getPage(): word;
  528. begin
  529. Result := adrPage div 16;
  530. end;
  531. function TSPS.getRAdr(): word;
  532. begin
  533. if (saveCnt = 0) then
  534. begin
  535. Result := 0;
  536. end;
  537. Result := saveaddr[saveCnt - 1];
  538. end;
  539. procedure TSPS.getStack(List: TStrings);
  540. var
  541. i: integer;
  542. begin
  543. for i := 0 to stack.Count - 1 do
  544. begin
  545. List.Add(IntToHex(stack.peek(i), 2));
  546. end;
  547. end;
  548. function TSPS.getARegister(): byte;
  549. begin
  550. Result := a;
  551. end;
  552. function TSPS.getBRegister(): byte;
  553. begin
  554. Result := b;
  555. end;
  556. function TSPS.getCRegister(): byte;
  557. begin
  558. Result := c;
  559. end;
  560. function TSPS.getDRegister(): byte;
  561. begin
  562. Result := d;
  563. end;
  564. function TSPS.getERegister(): byte;
  565. begin
  566. Result := e;
  567. end;
  568. function TSPS.getFRegister(): byte;
  569. begin
  570. Result := f;
  571. end;
  572. procedure TSPS.setTPSVersion(tpsversion: TTPSVersion);
  573. begin
  574. version := tpsversion;
  575. end;
  576. procedure TSPS.getCommands(list: TStrings);
  577. begin
  578. MCSStrings.copyArray2List(COMMANDS, list);
  579. end;
  580. procedure TSPS.getDatas(cmd: byte; list: TStrings);
  581. begin
  582. if (cmd = 0) then
  583. begin
  584. case version of
  585. Holtek, ATMega8: MCSStrings.copyArray2List(O_LIST_H, list);
  586. ATTiny84, Arduino: MCSStrings.copyArray2List(O_LIST_AT, list);
  587. end;
  588. end;
  589. if (cmd = 1) then
  590. begin
  591. MCSStrings.copyArray2List(DOUT_LIST, list);
  592. end;
  593. if (cmd = 2) then
  594. MCSStrings.copyArray2List(DELAY_LIST, list);
  595. if (cmd = 3) then
  596. MCSStrings.copyArray2List(JUMP_B_LIST, list);
  597. if (cmd = 4) then
  598. MCSStrings.copyArray2List(A_LIST, list);
  599. if (cmd = 5) then
  600. begin
  601. case version of
  602. Holtek: MCSStrings.copyArray2List(IS_A_LIST_H, list);
  603. ATMega8: MCSStrings.copyArray2List(IS_A_LIST_A8, list);
  604. ATTiny84, Arduino: MCSStrings.copyArray2List(IS_A_LIST_AT, list);
  605. end;
  606. end;
  607. if (cmd = 6) then
  608. begin
  609. case version of
  610. Holtek: MCSStrings.copyArray2List(A_IS_LIST_H, list);
  611. ATMega8: MCSStrings.copyArray2List(A_IS_LIST_A8, list);
  612. ATTiny84, Arduino: MCSStrings.copyArray2List(A_IS_LIST_AT, list);
  613. end;
  614. end;
  615. if (cmd = 7) then
  616. begin
  617. case version of
  618. Holtek, ATMega8: MCSStrings.copyArray2List(A_CALC_LIST_H, list);
  619. ATTiny84, Arduino: MCSStrings.copyArray2List(A_CALC_LIST_AT, list);
  620. end;
  621. end;
  622. if (cmd = 8) then
  623. begin
  624. case version of
  625. Holtek, ATMega8: MCSStrings.copyArray2List(PAGE_LIST_H, list);
  626. ATTiny84, Arduino: MCSStrings.copyArray2List(PAGE_LIST_AT, list);
  627. end;
  628. end;
  629. if (cmd = 9) then
  630. MCSStrings.copyArray2List(JUMP_LIST, list);
  631. if (cmd = 10) then
  632. MCSStrings.copyArray2List(C_LIST, list);
  633. if (cmd = 11) then
  634. MCSStrings.copyArray2List(D_LIST, list);
  635. if (cmd = 12) then
  636. begin
  637. case version of
  638. Holtek: MCSStrings.copyArray2List(SKIP_LIST_H, list);
  639. ATMega8: MCSStrings.copyArray2List(SKIP_LIST_A8, list);
  640. ATTiny84, Arduino: MCSStrings.copyArray2List(SKIP_LIST_AT, list);
  641. end;
  642. end;
  643. if (cmd = 13) then
  644. MCSStrings.copyArray2List(CALL_LIST, list);
  645. if (cmd = 14) then
  646. begin
  647. case version of
  648. Holtek, ATMega8: MCSStrings.copyArray2List(RET_LIST_H, list);
  649. ATTiny84, Arduino: MCSStrings.copyArray2List(RET_LIST_AT, list);
  650. end;
  651. end;
  652. if (cmd = 15) then
  653. begin
  654. case version of
  655. Holtek, ATMega8: MCSStrings.copyArray2List(F_LIST_H, list);
  656. ATTiny84, Arduino: MCSStrings.copyArray2List(F_LIST_AT, list);
  657. end;
  658. end;
  659. end;
  660. function TSPS.getCommandText(cmd, Data: byte): string;
  661. var
  662. list: TStrings;
  663. line: string;
  664. begin
  665. if ((cmd >= 0) and (cmd < 16)) then
  666. begin
  667. list := TStringList.Create;
  668. getDatas(cmd, list);
  669. if ((Data >= 0) and (Data < 16)) then
  670. line := COMMANDS[cmd] + ':' + list[Data];
  671. list.Free;
  672. end;
  673. Result := line;
  674. end;
  675. function TSPS.getJump(): byte;
  676. begin
  677. Result := jumpAddr;
  678. end;
  679. procedure TSPS.doNull(Data: byte);
  680. begin
  681. // Do nothing
  682. end;
  683. // output to port
  684. procedure TSPS.doPort(Data: byte);
  685. begin
  686. dout1 := (Data and $01) > 0;
  687. dout2 := (Data and $02) > 0;
  688. dout3 := (Data and $04) > 0;
  689. dout4 := (Data and $08) > 0;
  690. end;
  691. // delay in ms
  692. procedure TSPS.doDelay(Data: byte);
  693. var
  694. delayValue: integer;
  695. x: integer;
  696. begin
  697. case Data of
  698. 0: delayValue := 1;
  699. 1: delayValue := 2;
  700. 2: delayValue := 5;
  701. 3: delayValue := 10;
  702. 4: delayValue := 20;
  703. 5: delayValue := 50;
  704. 6: delayValue := 100;
  705. 7: delayValue := 200;
  706. 8: delayValue := 500;
  707. 9: delayValue := 1000;
  708. 10: delayValue := 2000;
  709. 11: delayValue := 5000;
  710. 12: delayValue := 10000;
  711. 13: delayValue := 20000;
  712. 14: delayValue := 30000;
  713. 15: delayValue := 60000;
  714. end;
  715. delayActive := True;
  716. repeat
  717. if (delayValue >= 100) then
  718. begin
  719. Dec(delayValue, 100);
  720. Sleep(100);
  721. delayCallback(delayValue);
  722. end;
  723. until ((delayValue <= 100) or stop);
  724. delayCallback(0);
  725. delayActive := False;
  726. end;
  727. // jump relative back
  728. procedure TSPS.doJumpBack(Data: byte);
  729. begin
  730. addr := addr - Data - 1;
  731. end;
  732. // a = data
  733. procedure TSPS.doSetA(Data: byte);
  734. begin
  735. a := Data;
  736. end;
  737. // a = somthing;
  738. procedure TSPS.doAIs(Data: byte);
  739. begin
  740. case Data of
  741. 1: a := b;
  742. 2: a := c;
  743. 3: a := d;
  744. 4:
  745. begin
  746. a := 0;
  747. if (din1) then
  748. a := a + 1;
  749. if (din2) then
  750. a := a + 2;
  751. if (din3) then
  752. a := a + 4;
  753. if (din4) then
  754. a := a + 8;
  755. end;
  756. 5: if (din1) then
  757. a := 1
  758. else
  759. a := 0;
  760. 6: if (din2) then
  761. a := 1
  762. else
  763. a := 0;
  764. 7: if (din3) then
  765. a := 1
  766. else
  767. a := 0;
  768. 8: if (din4) then
  769. a := 1
  770. else
  771. a := 0;
  772. 9: a := adc1 and $0f; //(Umrechnen auf 4 bit)
  773. 10: a := adc2 and $0f; //(Umrechnen auf 4 bit)
  774. 11: a := rc1 and $0f; //(Umrechnen auf 4 bit)
  775. 12: a := rc2 and $0f; //(Umrechnen auf 4 bit)
  776. 13: a := e;
  777. 14: a := f;
  778. 15: a := pop();
  779. end;
  780. end;
  781. // somthing = a;
  782. procedure TSPS.doIsA(Data: byte);
  783. var
  784. tmpValue: byte;
  785. begin
  786. case Data of
  787. 0: case version of
  788. ATTiny84, Arduino:
  789. begin
  790. tmpValue := b;
  791. b := a;
  792. a := tmpValue;
  793. end;
  794. end;
  795. 1: b := a;
  796. 2: c := a;
  797. 3: d := a;
  798. 4: doPort(a);
  799. 5: dout1 := (a and $01) > 0;
  800. 6: dout2 := (a and $01) > 0;
  801. 7: dout3 := (a and $01) > 0;
  802. 8: dout4 := (a and $01) > 0;
  803. 9:
  804. begin
  805. pwm1 := a * 16;
  806. case version of
  807. Holtek:
  808. begin
  809. pwm1 := a;
  810. end;
  811. end;
  812. end;
  813. 10: pwm2 := a * 16;
  814. 11:
  815. begin
  816. if (servo1.attached()) then
  817. servo1.Write((a * 10) + 10);
  818. end;
  819. 12:
  820. begin
  821. if (servo2.attached()) then
  822. servo2.Write((a * 10) + 10);
  823. end;
  824. 13: e := a;
  825. 14: f := a;
  826. 15: push(a);
  827. end;
  828. end;
  829. // calculations
  830. procedure TSPS.doCalc(Data: byte);
  831. begin
  832. case Data of
  833. 1: a := a + 1;
  834. 2: a := a - 1;
  835. 3: a := a + b;
  836. 4: a := a - b;
  837. 5: a := a * b;
  838. 6: a := a div b;
  839. 7: a := a and b;
  840. 8: a := a or b;
  841. 9: a := a xor b;
  842. 10: a := not a;
  843. 11: case version of
  844. ATTiny84, Arduino: a := a mod b;
  845. end;
  846. 12: case version of
  847. ATTiny84, Arduino: a := a + 16 * b;
  848. end;
  849. 13: case version of
  850. ATTiny84, Arduino: a := b - a;
  851. end;
  852. 14: case version of
  853. ATTiny84, Arduino: a := a SHR 1;
  854. end;
  855. 15: case version of
  856. ATTiny84, Arduino: a := a SHL 1;
  857. end;
  858. end;
  859. case version of
  860. Holtek, ATMega8: a := a and 15;
  861. end;
  862. end;
  863. // setting page
  864. procedure TSPS.doPage(Data: byte);
  865. begin
  866. adrPage := Data * 16;
  867. end;
  868. // jump absolute
  869. procedure TSPS.doJump(Data: byte);
  870. begin
  871. addr := adrPage + Data;
  872. end;
  873. // counting with c register
  874. procedure TSPS.doCCount(Data: byte);
  875. begin
  876. if (c > 0) then
  877. begin
  878. c := c - 1;
  879. c := c and $0F;
  880. doJump(Data);
  881. end;
  882. end;
  883. // counting with d register
  884. procedure TSPS.doDCount(Data: byte);
  885. begin
  886. if (d > 0) then
  887. begin
  888. d := d - 1;
  889. d := d and $0F;
  890. doJump(Data);
  891. end;
  892. end;
  893. // simple comdition = true skip next command
  894. procedure TSPS.doSkipIf(Data: byte);
  895. begin
  896. case (Data) of
  897. 0: if (a = 0) then
  898. case version of
  899. ATTiny84, Arduino: addr := addr + 1;
  900. end;
  901. 1: if (a > b) then
  902. addr := addr + 1;
  903. 2: if (a < b) then
  904. addr := addr + 1;
  905. 3: if (a = b) then
  906. addr := addr + 1;
  907. 4: if (din1) then
  908. addr := addr + 1;
  909. 5: if (din2) then
  910. addr := addr + 1;
  911. 6: if (din3) then
  912. addr := addr + 1;
  913. 7: if (din4) then
  914. addr := addr + 1;
  915. 8: if (not din1) then
  916. addr := addr + 1;
  917. 9: if (not din2) then
  918. addr := addr + 1;
  919. 10: if (not din3) then
  920. addr := addr + 1;
  921. 11: if (not din4) then
  922. addr := addr + 1;
  923. 12: if (sw_sel) then
  924. addr := addr + 1;
  925. 13: if (sw_prg) then
  926. addr := addr + 1;
  927. 14: if (not sw_sel) then
  928. addr := addr + 1;
  929. 15: if (not sw_prg) then
  930. addr := addr + 1;
  931. end;
  932. end;
  933. // calling a subroutine
  934. procedure TSPS.doCall(Data: byte);
  935. begin
  936. saveaddr[saveCnt] := addr;
  937. case version of
  938. ATTiny84, Arduino: saveCnt := saveCnt + 1;
  939. end;
  940. addr := adrpage + Data;
  941. end;
  942. // calling a subroutine, calling return and restart
  943. procedure TSPS.doCallSub(Data: byte);
  944. begin
  945. if (Data = 0) then
  946. begin
  947. case version of
  948. ATTiny84, Arduino:
  949. begin
  950. if (saveCnt = 0) then
  951. begin
  952. doReset();
  953. exit;
  954. end;
  955. saveCnt := saveCnt - 1;
  956. end;
  957. end;
  958. addr := saveaddr[saveCnt];
  959. exit;
  960. end;
  961. if ((Data <= 6) and ((version = ATTiny84) or (version = Arduino))) then
  962. begin
  963. // call subroutine number
  964. saveaddr[saveCnt] := addr;
  965. saveCnt := saveCnt + 1;
  966. addr := subs[Data];
  967. exit;
  968. end;
  969. if ((Data = $0f) and ((version = ATTiny84) or (version = Arduino))) then
  970. begin
  971. doReset();
  972. exit;
  973. end;
  974. end;
  975. procedure TSPS.doByte(Data: byte);
  976. var
  977. Value: integer;
  978. begin
  979. // Some byte commands
  980. case (Data) of
  981. 0: case version of
  982. ATTiny84, Arduino: a := adc1;
  983. end;
  984. 1: case version of
  985. ATTiny84, Arduino: a := adc2;
  986. end;
  987. 2: case version of
  988. ATTiny84, Arduino: a := rc1;
  989. end;
  990. 3: case version of
  991. ATTiny84, Arduino: a := rc2;
  992. end;
  993. 4: pwm1 := a;
  994. 5: pwm2 := a;
  995. 6:
  996. begin
  997. if (servo1.attached()) then
  998. begin
  999. Value := (180 * a) div 255;
  1000. servo1.Write(Value);
  1001. end;
  1002. end;
  1003. 7:
  1004. begin
  1005. if (servo2.attached()) then
  1006. begin
  1007. Value := (180 * a) div 255;
  1008. servo2.Write(Value);
  1009. end;
  1010. end;
  1011. 8:
  1012. case version of
  1013. ATTiny84, Arduino: doTone(Data);
  1014. end;
  1015. end;
  1016. end;
  1017. procedure TSPS.doTone(Data: byte);
  1018. begin
  1019. if (a in [36..109]) then
  1020. tone := a
  1021. else
  1022. tone := 0;
  1023. end;
  1024. procedure TSPS.push(Data: byte);
  1025. begin
  1026. stack.Push(Data);
  1027. end;
  1028. function TSPS.pop(): byte;
  1029. begin
  1030. Result := stack.pop;
  1031. end;
  1032. constructor TSPS.Create;
  1033. begin
  1034. servo1 := TServo.Create();
  1035. servo2 := TServo.Create();
  1036. stack := TByteStack.Create;
  1037. stop := False;
  1038. delayActive := False;
  1039. end;
  1040. destructor TSPS.Destroy;
  1041. begin
  1042. inherited Destroy;
  1043. servo1.Free;
  1044. servo2.Free;
  1045. stack.Free;
  1046. end;
  1047. procedure TSPS.setDelayCallback(callback: TDelayCallback);
  1048. begin
  1049. delayCallback := callback;
  1050. end;
  1051. end.