raspberrypi-pixtend-musicplayer.awlpro 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  2. <!-- Awlsim project file generated by awlsim-0.66.0-pre -->
  3. <awlsim_project date_create="2018-02-09 21:25:51.784572"
  4. date_modify="2018-07-08 18:00:06.926449"
  5. format_version="1">
  6. <!-- CPU core configuration -->
  7. <cpu>
  8. <!-- CPU core feature specification -->
  9. <specs call_stack_size="256"
  10. nr_accus="2"
  11. nr_counters="256"
  12. nr_flags="2048"
  13. nr_inputs="128"
  14. nr_localbytes="1024"
  15. nr_outputs="128"
  16. nr_timers="256"
  17. parenthesis_stack_size="7" />
  18. <!-- CPU core configuration -->
  19. <config clock_memory_byte="-1"
  20. cycle_time_limit_us="1000000"
  21. ext_insns_enable="1"
  22. mnemonics="0"
  23. ob_startinfo_enable="0"
  24. run_time_limit_us="-1" />
  25. </cpu>
  26. <!-- AWL/STL language configuration -->
  27. <language_awl>
  28. <!-- AWL/STL source code -->
  29. <source enabled="1"
  30. name="OB 1"
  31. type="0"><![CDATA[
  32. ORGANIZATION_BLOCK OB 1
  33. VAR_TEMP
  34. OB1_EV_CLASS : BYTE; // Bits 0-3 = 1 (Coming event), Bits 4-7 = 1 (Event class 1)
  35. OB1_SCAN_1 : BYTE; // 1 (Cold restart scan 1 of OB 1), 3 (Scan 2-n of OB 1)
  36. OB1_PRIORITY : BYTE; // Priority of OB execution
  37. OB1_OB_NUMBR : BYTE; // 1 (Organization block 1, OB 1)
  38. OB1_RESERVED_1 : BYTE;
  39. OB1_RESERVED_2 : BYTE;
  40. OB1_PREV_CYCLE : INT; // Cycle time of previous OB 1 scan (milliseconds)
  41. OB1_MIN_CYCLE : INT; // Minimum cycle time of OB 1 (milliseconds)
  42. OB1_MAX_CYCLE : INT; // Maximum cycle time of OB 1 (milliseconds)
  43. OB1_DATE_TIME : DATE_AND_TIME; // Date and time OB 1 started
  44. END_VAR
  45. BEGIN
  46. // Run the music player
  47. CALL "FB_musicPlayer", DB 10 (
  48. volume := 15,
  49. base_speed := T#2000ms,
  50. song_DB := "DB_song",
  51. )
  52. END_ORGANIZATION_BLOCK
  53. DATA_BLOCK DB 10
  54. "FB_musicPlayer"
  55. BEGIN
  56. END_DATA_BLOCK
  57. ]]></source>
  58. <!-- AWL/STL source code -->
  59. <source enabled="1"
  60. name="player"
  61. type="0"><![CDATA[
  62. FUNCTION_BLOCK "FB_musicPlayer"
  63. TITLE = PWM based music player
  64. AUTHOR : Michael Buesch <m@bues.ch>
  65. // License : GNU/GPL 2+
  66. VAR_INPUT
  67. volume : INT;
  68. base_speed : TIME;
  69. song_DB : BLOCK_DB;
  70. END_VAR
  71. VAR
  72. notes_index : INT;
  73. octave_shift : INT;
  74. sharp : BOOL;
  75. tie : BOOL;
  76. wait_time_active : BOOL;
  77. wait_timestamp : TIME;
  78. prev_note_id : BYTE;
  79. prev_note_value : BYTE;
  80. END_VAR
  81. VAR_TEMP
  82. cur_note : BYTE;
  83. cur_note_id : BYTE;
  84. cur_note_value : BYTE;
  85. base_freq : DINT;
  86. deci_hz : INT;
  87. period : WORD;
  88. remaining_ms : TIME;
  89. now : TIME;
  90. END_VAR
  91. BEGIN
  92. // Get the current time
  93. CALL SFC 64 (
  94. RET_VAL := #now
  95. )
  96. // Check if we need to wait
  97. U #wait_time_active
  98. SPBN NWAI
  99. L #now
  100. L #wait_timestamp
  101. -D
  102. SLD 1 // sign extension
  103. SSD 1 // sign extension
  104. L 0
  105. <D
  106. BEB
  107. CLR
  108. = #wait_time_active
  109. NWAI: NOP 0
  110. // Open the song we are playing
  111. AUF #song_DB
  112. // Get current note
  113. L #notes_index
  114. SLW 3
  115. LAR1
  116. L DBB [AR1, P#0.0]
  117. T #cur_note
  118. // End of note table?
  119. L #cur_note
  120. L B#16#FF
  121. <>I
  122. SPB NEND
  123. L 0
  124. T #notes_index
  125. L DBB 0
  126. T #cur_note
  127. NEND: NOP 0
  128. // Extract note ID
  129. L #cur_note
  130. UW W#16#0F
  131. T #cur_note_id
  132. // Extract note value
  133. L #cur_note
  134. UW W#16#70
  135. SRW 4
  136. T #cur_note_value
  137. // If this is a special note, handle it.
  138. L #cur_note_id
  139. L W#16#F
  140. ==I
  141. SPB SPEC
  142. // Check if the current note is equal to the previous note.
  143. L #cur_note_id
  144. L #prev_note_id
  145. ==I
  146. SPB SAME
  147. // Tune the note.
  148. // Get the note frequency in deci-Hz.
  149. TUNE: AUF "DB_notes"
  150. U #sharp
  151. SPBN NOSH
  152. AUF "DB_notes_sharp"
  153. NOSH: L #cur_note_id
  154. SLW 4
  155. LAR1
  156. L DBW [AR1, P#0.0]
  157. T #deci_hz
  158. // Octave shift the frequency.
  159. L #octave_shift
  160. L 0
  161. >=I
  162. SPB POSO
  163. // Negative octave shift
  164. L #octave_shift
  165. NEGI
  166. L #deci_hz
  167. SRW
  168. SPA OCTE
  169. // Positive octave shift
  170. POSO: L #octave_shift
  171. L #deci_hz
  172. SLW
  173. OCTE: T #deci_hz
  174. // Calculate the PWM period from the frequency.
  175. L #deci_hz
  176. L 0
  177. ==I
  178. SPB NPER
  179. L L#20000000 // pwm_baseFreqHz * 10
  180. L #deci_hz
  181. /D
  182. NPER: T #period
  183. // Write period to PWM output hardware
  184. CALL "FC_setPWM" (
  185. period := #period,
  186. volume := #volume,
  187. )
  188. // Calculate the wait timestamp from the current note value.
  189. CALL "FC_calcWaitTime" (
  190. now := #now,
  191. note_value := #cur_note_value,
  192. base_speed := #base_speed,
  193. wait_timestamp := #wait_timestamp,
  194. wait_time_active := #wait_time_active,
  195. )
  196. // We are done with this note.
  197. // Reset all flags.
  198. CLR
  199. = #sharp
  200. = #tie
  201. L #cur_note_id
  202. T #prev_note_id
  203. L #cur_note_value
  204. T #prev_note_value
  205. SPA NEXT
  206. // If this is a special flags note, handle it.
  207. SPEC: L #cur_note_value
  208. SPL INVA // Invalid
  209. SPA SHRP // Activate "sharp" (Kreuz)
  210. SPA DOT // Activate "dot" (Punktierung)
  211. SPA TIE // Activate "tie" (Haltebogen)
  212. SPA SHUP // Shift one octave up
  213. SPA SHDN // Shift one octave down
  214. SPA INVA // Invalid
  215. SPA INVA // Invalid
  216. SPA INVA // Invalid
  217. INVA: BEA
  218. // Activate "sharp" (Kreuz)
  219. SHRP: SET
  220. = #sharp
  221. SPA NEXT
  222. // Activate "dot" (Punktierung)
  223. // Get the value of the previous note (that is the currenly tuned one)
  224. // and wait for half its time.
  225. DOT: L #prev_note_value
  226. + 1 // Decrease value by 50%
  227. T #prev_note_value
  228. CALL "FC_calcWaitTime" (
  229. now := #now,
  230. note_value := #prev_note_value,
  231. base_speed := #base_speed,
  232. wait_timestamp := #wait_timestamp,
  233. wait_time_active := #wait_time_active,
  234. )
  235. SPA NEXT
  236. // Activate "tie" (Haltebogen)
  237. TIE: SET
  238. = #tie
  239. SPA NEXT
  240. // Shift one octave up
  241. SHUP: L #octave_shift
  242. + 1
  243. T #octave_shift
  244. SPA NEXT
  245. // Shift one octave down
  246. SHDN: L #octave_shift
  247. + -1
  248. T #octave_shift
  249. SPA NEXT
  250. // The current note is the same as the previous one.
  251. // If "tie" is not active, deactivate the PWM and wait
  252. // a tiny amount of time. Then re-activate the note.
  253. // If "tie" is active, tune the note.
  254. SAME: U #tie
  255. SPB TUNE
  256. CALL "FC_setPWM" (
  257. period := W#16#0,
  258. volume := #volume,
  259. )
  260. L #now
  261. L T#30ms
  262. +D
  263. UD DW#16#7FFFFFFF
  264. T #wait_timestamp
  265. SET
  266. = #wait_time_active
  267. // Set "tie" to re-activate the note
  268. // after the wait time has passed.
  269. SET
  270. = #tie
  271. SPB NINC
  272. // Increment notes index
  273. NEXT: L #notes_index
  274. + 1
  275. T #notes_index
  276. NINC: BE
  277. END_FUNCTION_BLOCK
  278. FUNCTION "FC_setPWM" : VOID
  279. VAR_INPUT
  280. period : WORD;
  281. volume : INT;
  282. END_VAR
  283. VAR_TEMP
  284. volume_shift : INT;
  285. END_VAR
  286. BEGIN
  287. // Calculate the duty cycle shift from the volume.
  288. // #volume can be 0-15
  289. L 15
  290. L #volume
  291. -I
  292. + 1
  293. T #volume_shift
  294. // Write period to PWM output hardware
  295. L #period
  296. T "pwm_period"
  297. // Write duty cycle to PWM output hardware
  298. L #volume_shift
  299. L #period
  300. SRW
  301. T "pwm0"
  302. END_FUNCTION
  303. FUNCTION "FC_calcWaitTime" : VOID
  304. VAR_INPUT
  305. now : TIME;
  306. note_value : BYTE;
  307. base_speed : TIME;
  308. END_VAR
  309. VAR_OUTPUT
  310. wait_timestamp : TIME;
  311. wait_time_active : BOOL;
  312. END_VAR
  313. VAR_TEMP
  314. remaining_ms : TIME;
  315. END_VAR
  316. BEGIN
  317. // Calculate the remaining time from the note value.
  318. L #note_value
  319. L #base_speed // base speed, in milliseconds
  320. SRW
  321. T #remaining_ms
  322. // Calculate the next timestamp to wait for.
  323. L #now
  324. L #remaining_ms
  325. +D
  326. UD DW#16#7FFFFFFF
  327. T #wait_timestamp
  328. SET
  329. = #wait_time_active
  330. END_FUNCTION
  331. ]]></source>
  332. <!-- AWL/STL source code -->
  333. <source enabled="1"
  334. name="notes"
  335. type="0"><![CDATA[
  336. // Note frequencies in 0.1 Hz
  337. DATA_BLOCK "DB_notes"
  338. STRUCT
  339. note_freqs : ARRAY [0 .. 14] OF INT;
  340. END_STRUCT;
  341. BEGIN
  342. note_freqs[0] := 0;
  343. note_freqs[1] := 2616; // c'
  344. note_freqs[2] := 2937; // d'
  345. note_freqs[3] := 3296; // e'
  346. note_freqs[4] := 3492; // f'
  347. note_freqs[5] := 3919; // g'
  348. note_freqs[6] := 4400; // a'
  349. note_freqs[7] := 4939; // h'
  350. note_freqs[8] := 5233; // c''
  351. note_freqs[9] := 5873; // d''
  352. note_freqs[10] := 6593; // e''
  353. note_freqs[11] := 6985; // f''
  354. note_freqs[12] := 7840; // g''
  355. note_freqs[13] := 8800; // a''
  356. note_freqs[14] := 9878; // h''
  357. END_DATA_BLOCK
  358. // Sharp note frequencies in 0.1 Hz
  359. DATA_BLOCK "DB_notes_sharp"
  360. STRUCT
  361. note_freqs : ARRAY [0 .. 14] OF INT;
  362. END_STRUCT;
  363. BEGIN
  364. note_freqs[0] := 0;
  365. note_freqs[1] := 2772; // cis'
  366. note_freqs[2] := 3111; // dis'
  367. note_freqs[3] := 3296; // e'
  368. note_freqs[4] := 3700; // fis'
  369. note_freqs[5] := 4153; // gis'
  370. note_freqs[6] := 4662; // ais'
  371. note_freqs[7] := 4939; // h'
  372. note_freqs[8] := 5544; // cis''
  373. note_freqs[9] := 6223; // dis''
  374. note_freqs[10] := 6593; // e''
  375. note_freqs[11] := 7400; // fis''
  376. note_freqs[12] := 8306; // gis''
  377. note_freqs[13] := 9323; // ais''
  378. note_freqs[14] := 9878; // h''
  379. END_DATA_BLOCK
  380. ]]></source>
  381. <!-- AWL/STL source code -->
  382. <source enabled="1"
  383. name="song"
  384. type="0"><![CDATA[
  385. // The Free Software Song
  386. // Sadi moma bela loza (Bulgarian folk song)
  387. // Words by Richard Stallman, the Free Software Foundation http://fsf.org/
  388. // Richard Stallman and the Free Software Foundation claim no copyright on this song.
  389. // The official homepage for this song is http://www.gnu.org/music/free-software-song.html
  390. DATA_BLOCK "DB_song"
  391. STRUCT
  392. SONG : ARRAY [0 .. 57] OF BYTE;
  393. END_STRUCT;
  394. BEGIN
  395. SONG[0] := B#16#29;
  396. SONG[1] := B#16#38;
  397. SONG[2] := B#16#27;
  398. SONG[3] := B#16#26;
  399. SONG[4] := B#16#27;
  400. SONG[5] := B#16#38;
  401. SONG[6] := B#16#37;
  402. SONG[7] := B#16#2F;
  403. SONG[8] := B#16#36;
  404. SONG[9] := B#16#25;
  405. SONG[10] := B#16#25;
  406. SONG[11] := B#16#1F;
  407. SONG[12] := B#16#26;
  408. SONG[13] := B#16#1F;
  409. SONG[14] := B#16#2F;
  410. SONG[15] := B#16#37;
  411. SONG[16] := B#16#28;
  412. SONG[17] := B#16#1F;
  413. SONG[18] := B#16#27;
  414. SONG[19] := B#16#37;
  415. SONG[20] := B#16#29;
  416. SONG[21] := B#16#26;
  417. SONG[22] := B#16#1F;
  418. SONG[23] := B#16#16;
  419. SONG[24] := B#16#29;
  420. SONG[25] := B#16#2F;
  421. SONG[26] := B#16#38;
  422. SONG[27] := B#16#2F;
  423. SONG[28] := B#16#17;
  424. SONG[29] := B#16#29;
  425. SONG[30] := B#16#38;
  426. SONG[31] := B#16#27;
  427. SONG[32] := B#16#26;
  428. SONG[33] := B#16#27;
  429. SONG[34] := B#16#38;
  430. SONG[35] := B#16#37;
  431. SONG[36] := B#16#2F;
  432. SONG[37] := B#16#36;
  433. SONG[38] := B#16#25;
  434. SONG[39] := B#16#25;
  435. SONG[40] := B#16#1F;
  436. SONG[41] := B#16#26;
  437. SONG[42] := B#16#1F;
  438. SONG[43] := B#16#2F;
  439. SONG[44] := B#16#37;
  440. SONG[45] := B#16#28;
  441. SONG[46] := B#16#1F;
  442. SONG[47] := B#16#27;
  443. SONG[48] := B#16#37;
  444. SONG[49] := B#16#29;
  445. SONG[50] := B#16#26;
  446. SONG[51] := B#16#1F;
  447. SONG[52] := B#16#16;
  448. SONG[53] := B#16#26;
  449. SONG[54] := B#16#1F;
  450. SONG[55] := B#16#2F;
  451. SONG[56] := B#16#16;
  452. SONG[57] := B#16#FF;
  453. END_DATA_BLOCK
  454. ]]></source>
  455. </language_awl>
  456. <!-- Symbol table configuration -->
  457. <symbols>
  458. <!-- symbol table source code -->
  459. <source enabled="1"
  460. name="Main table"
  461. type="3"><![CDATA[
  462. 126,pwm_period AW 0 WORD
  463. 126,pwm0 AW 2 WORD
  464. 126,DB_notes DB 100 DB 100
  465. 126,DB_notes_sharp DB 101 DB 101
  466. 126,DB_song DB 1 DB 1
  467. 126,FB_musicPlayer FB 1 FB 1
  468. 126,FC_setPWM FC 1 FC 1
  469. 126,FC_calcWaitTime FC 2 FC 2
  470. ]]></source>
  471. </symbols>
  472. <!-- Core server link configuration -->
  473. <core_link>
  474. <!-- Locally spawned core server -->
  475. <spawn_local enable="0"
  476. interpreters="$DEFAULT"
  477. port_range_begin="4183"
  478. port_range_end="8278" />
  479. <!-- Remote server connection -->
  480. <connect host="pilc"
  481. port="4151"
  482. timeout_ms="3000" />
  483. <!-- Transport tunnel -->
  484. <tunnel local_port="-1"
  485. type="1">
  486. <ssh executable="ssh"
  487. port="22"
  488. user="pi" />
  489. </tunnel>
  490. </core_link>
  491. <!-- Hardware modules configuration -->
  492. <hardware>
  493. <!-- Loaded hardware module -->
  494. <module name="pixtend">
  495. <params>
  496. <param name="analogIn0_10V"
  497. value="True" />
  498. <param name="analogIn0_addr" />
  499. <param name="analogIn0_nos"
  500. value="10" />
  501. <param name="analogIn1_10V"
  502. value="True" />
  503. <param name="analogIn1_addr" />
  504. <param name="analogIn1_nos"
  505. value="10" />
  506. <param name="analogIn2_addr" />
  507. <param name="analogIn2_nos"
  508. value="10" />
  509. <param name="analogIn3_addr" />
  510. <param name="analogIn3_nos"
  511. value="10" />
  512. <param name="analogIn_kHz"
  513. value="125" />
  514. <param name="analogOut0_addr" />
  515. <param name="analogOut1_addr" />
  516. <param name="boardType"
  517. value="auto" />
  518. <param name="digitalIn0_addr" />
  519. <param name="digitalIn1_addr" />
  520. <param name="digitalIn2_addr" />
  521. <param name="digitalIn3_addr" />
  522. <param name="digitalIn4_addr" />
  523. <param name="digitalIn5_addr" />
  524. <param name="digitalIn6_addr" />
  525. <param name="digitalIn7_addr" />
  526. <param name="digitalOut0_addr" />
  527. <param name="digitalOut1_addr" />
  528. <param name="digitalOut2_addr" />
  529. <param name="digitalOut3_addr" />
  530. <param name="digitalOut4_addr" />
  531. <param name="digitalOut5_addr" />
  532. <param name="enabled"
  533. value="True" />
  534. <param name="gpio0_addr" />
  535. <param name="gpio0_pullup"
  536. value="False" />
  537. <param name="gpio1_addr" />
  538. <param name="gpio1_pullup"
  539. value="False" />
  540. <param name="gpio2_addr" />
  541. <param name="gpio2_pullup"
  542. value="False" />
  543. <param name="gpio3_addr" />
  544. <param name="gpio3_pullup"
  545. value="False" />
  546. <param name="inputAddressBase"
  547. value="0" />
  548. <param name="outputAddressBase"
  549. value="0" />
  550. <param name="pollIntMs"
  551. value="25" />
  552. <param name="pwm0A_addr"
  553. value="AW 2" />
  554. <param name="pwm0B_addr" />
  555. <param name="pwm0_baseFreqHz"
  556. value="2000000" />
  557. <param name="pwm0_mode"
  558. value="dutycycle" />
  559. <param name="pwm0_period"
  560. value="AW 0" />
  561. <param name="pwm1A_addr" />
  562. <param name="pwm1B_addr" />
  563. <param name="pwm1_baseFreqHz"
  564. value="0" />
  565. <param name="pwm1_mode"
  566. value="dutycycle" />
  567. <param name="pwm1_period" />
  568. <param name="relay0_addr" />
  569. <param name="relay1_addr" />
  570. <param name="relay2_addr" />
  571. <param name="relay3_addr" />
  572. <param name="rs485"
  573. value="False" />
  574. </params>
  575. </module>
  576. </hardware>
  577. <!-- Graphical user interface configuration -->
  578. <gui>
  579. <editor autoindent="1"
  580. paste_autoindent="1"
  581. validation="1" />
  582. </gui>
  583. </awlsim_project>