usps.pas 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155
  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', '', '');
  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: pwm1 := a * 16;
  804. 10: pwm2 := a * 16;
  805. 11:
  806. begin
  807. if (servo1.attached()) then
  808. servo1.Write((a * 10) + 10);
  809. end;
  810. 12:
  811. begin
  812. if (servo2.attached()) then
  813. servo2.Write((a * 10) + 10);
  814. end;
  815. 13: e := a;
  816. 14: f := a;
  817. 15: push(a);
  818. end;
  819. end;
  820. // calculations
  821. procedure TSPS.doCalc(Data: byte);
  822. begin
  823. case Data of
  824. 1: a := a + 1;
  825. 2: a := a - 1;
  826. 3: a := a + b;
  827. 4: a := a - b;
  828. 5: a := a * b;
  829. 6: a := a div b;
  830. 7: a := a and b;
  831. 8: a := a or b;
  832. 9: a := a xor b;
  833. 10: a := not a;
  834. 11: case version of
  835. ATTiny84, Arduino: a := a mod b;
  836. end;
  837. 12: case version of
  838. ATTiny84, Arduino: a := a + 16 * b;
  839. end;
  840. 13: case version of
  841. ATTiny84, Arduino: a := b - a;
  842. end;
  843. end;
  844. case version of
  845. Holtek, ATMega8: a := a and 15;
  846. end;
  847. end;
  848. // setting page
  849. procedure TSPS.doPage(Data: byte);
  850. begin
  851. adrPage := Data * 16;
  852. end;
  853. // jump absolute
  854. procedure TSPS.doJump(Data: byte);
  855. begin
  856. addr := adrPage + Data;
  857. end;
  858. // counting with c register
  859. procedure TSPS.doCCount(Data: byte);
  860. begin
  861. if (c > 0) then
  862. begin
  863. c := c - 1;
  864. c := c and $0F;
  865. doJump(Data);
  866. end;
  867. end;
  868. // counting with d register
  869. procedure TSPS.doDCount(Data: byte);
  870. begin
  871. if (d > 0) then
  872. begin
  873. d := d - 1;
  874. d := d and $0F;
  875. doJump(Data);
  876. end;
  877. end;
  878. // simple comdition = true skip next command
  879. procedure TSPS.doSkipIf(Data: byte);
  880. begin
  881. case (Data) of
  882. 0: if (a = 0) then
  883. case version of
  884. ATTiny84, Arduino: addr := addr + 1;
  885. end;
  886. 1: if (a > b) then
  887. addr := addr + 1;
  888. 2: if (a < b) then
  889. addr := addr + 1;
  890. 3: if (a = b) then
  891. addr := addr + 1;
  892. 4: if (din1) then
  893. addr := addr + 1;
  894. 5: if (din2) then
  895. addr := addr + 1;
  896. 6: if (din3) then
  897. addr := addr + 1;
  898. 7: if (din4) then
  899. addr := addr + 1;
  900. 8: if (not din1) then
  901. addr := addr + 1;
  902. 9: if (not din2) then
  903. addr := addr + 1;
  904. 10: if (not din3) then
  905. addr := addr + 1;
  906. 11: if (not din4) then
  907. addr := addr + 1;
  908. 12: if (sw_sel) then
  909. addr := addr + 1;
  910. 13: if (sw_prg) then
  911. addr := addr + 1;
  912. 14: if (not sw_sel) then
  913. addr := addr + 1;
  914. 15: if (not sw_prg) then
  915. addr := addr + 1;
  916. end;
  917. end;
  918. // calling a subroutine
  919. procedure TSPS.doCall(Data: byte);
  920. begin
  921. saveaddr[saveCnt] := addr;
  922. case version of
  923. ATTiny84, Arduino: saveCnt := saveCnt + 1;
  924. end;
  925. addr := adrpage + Data;
  926. end;
  927. // calling a subroutine, calling return and restart
  928. procedure TSPS.doCallSub(Data: byte);
  929. begin
  930. if (Data = 0) then
  931. begin
  932. case version of
  933. ATTiny84, Arduino:
  934. begin
  935. if (saveCnt = 0) then
  936. begin
  937. doReset();
  938. exit;
  939. end;
  940. saveCnt := saveCnt - 1;
  941. end;
  942. end;
  943. addr := saveaddr[saveCnt];
  944. exit;
  945. end;
  946. if ((Data <= 6) and ((version = ATTiny84) or (version = Arduino))) then
  947. begin
  948. // call subroutine number
  949. saveaddr[saveCnt] := addr;
  950. saveCnt := saveCnt + 1;
  951. addr := subs[Data];
  952. exit;
  953. end;
  954. if ((Data = $0f) and ((version = ATTiny84) or (version = Arduino))) then
  955. begin
  956. doReset();
  957. exit;
  958. end;
  959. end;
  960. procedure TSPS.doByte(Data: byte);
  961. var
  962. Value: integer;
  963. begin
  964. // Some byte commands
  965. case (Data) of
  966. 0: case version of
  967. ATTiny84, Arduino: a := adc1;
  968. end;
  969. 1: case version of
  970. ATTiny84, Arduino: a := adc2;
  971. end;
  972. 2: case version of
  973. ATTiny84, Arduino: a := rc1;
  974. end;
  975. 3: case version of
  976. ATTiny84, Arduino: a := rc2;
  977. end;
  978. 4: pwm1 := a;
  979. 5: pwm2 := a;
  980. 6:
  981. begin
  982. if (servo1.attached()) then
  983. begin
  984. Value := (180 * a) div 255;
  985. servo1.Write(Value);
  986. end;
  987. end;
  988. 7:
  989. begin
  990. if (servo2.attached()) then
  991. begin
  992. Value := (180 * a) div 255;
  993. servo2.Write(Value);
  994. end;
  995. end;
  996. 8:
  997. case version of
  998. ATTiny84, Arduino: doTone(Data);
  999. end;
  1000. end;
  1001. end;
  1002. procedure TSPS.doTone(Data: byte);
  1003. begin
  1004. if (a in [36..109]) then
  1005. tone := a
  1006. else
  1007. tone := 0;
  1008. end;
  1009. procedure TSPS.push(Data: byte);
  1010. begin
  1011. stack.Push(Data);
  1012. end;
  1013. function TSPS.pop(): byte;
  1014. begin
  1015. Result := stack.pop;
  1016. end;
  1017. constructor TSPS.Create;
  1018. begin
  1019. servo1 := TServo.Create();
  1020. servo2 := TServo.Create();
  1021. stack := TByteStack.Create;
  1022. stop := False;
  1023. delayActive := False;
  1024. end;
  1025. destructor TSPS.Destroy;
  1026. begin
  1027. inherited Destroy;
  1028. servo1.Free;
  1029. servo2.Free;
  1030. stack.Free;
  1031. end;
  1032. procedure TSPS.setDelayCallback(callback: TDelayCallback);
  1033. begin
  1034. delayCallback := callback;
  1035. end;
  1036. end.