raspberrypi-pixtend-musicplayer.awlpro 14 KB

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