Mercurial > vba-clojure
diff clojure/com/aurellem/run/music.clj @ 424:7bd806c4dbb6
changed assembly to handle mini-midi messages of different lengths.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Mon, 23 Apr 2012 04:45:55 -0500 |
parents | 971bd1774eab |
children | df4e03672b05 |
line wrap: on
line diff
1.1 --- a/clojure/com/aurellem/run/music.clj Tue Apr 17 06:53:48 2012 -0500 1.2 +++ b/clojure/com/aurellem/run/music.clj Mon Apr 23 04:45:55 2012 -0500 1.3 @@ -62,6 +62,44 @@ 1.4 (store (Integer/parseInt "00000000" 2) 0xFF22) 1.5 (store (Integer/parseInt "00000000" 2) 0xFF23)])) 1.6 1.7 + 1.8 +;; mini-midi syntax 1.9 + 1.10 +;; codes 1.11 +;; note-code == 0x00 1.12 +;; change-duty-code = 0x01 1.13 +;; silence-code = 0x02 1.14 + 1.15 +;; silence format 1.16 +;; 2 bytes 1.17 +;; [silence-code (0x02)] 1.18 +;; [duration-8-bits] 1.19 + 1.20 +;; note data format 1.21 +;; 4 bytes 1.22 +;; [note-code (0x00)] 1.23 +;; [volume-4-bits 0 frequency-high-3-bits] 1.24 +;; [frequengy-low-8-bits] 1.25 +;; [duration-8-bits] 1.26 + 1.27 +;; change-duty-format 1.28 +;; 2 bytes 1.29 +;; [change-duty-code (0x01)] 1.30 +;; [new-duty] 1.31 + 1.32 +(defn do-message 1.33 + "Read the message which starts at the current value of HL and do 1.34 + what it says. Duration is left in A, and HL is advanced 1.35 + appropraitely." 1.36 + [] 1.37 + 1.38 + ) 1.39 + 1.40 + 1.41 + 1.42 + 1.43 + 1.44 + 1.45 (defn play-note 1.46 "Play the note referenced by HL in the appropiate channel. 1.47 Leaves desired-duration in A." 1.48 @@ -82,14 +120,12 @@ 1.49 0xE0 1.50 0x18 ;; set frequency-low-bits 1.51 1.52 - 0x7E ;; load duration 1.53 - 0x2B ;; 1.54 - 0x2B ;; HL-2 -> HL 1.55 + 0x2A ;; load duration 1.56 ]) 1.57 1.58 (defn music-step [] 1.59 (flatten 1.60 - [(play-note) 1.61 + [ 1.62 0xF5 ;; push A 1.63 0xF0 1.64 0x05 ;; load current ticks 1.65 @@ -112,33 +148,13 @@ 1.66 ;; go to next note ; set current set ticks to 0. 1.67 1.68 0x20 1.69 - 0x05 1.70 + (+ (count (play-note)) 2) 1.71 1.72 - 0x23 1.73 - 0x23 1.74 - 0x23 ;; HL + 3 -> HL 1.75 + (play-note) 1.76 1.77 0x0E 1.78 0x00])) ;; 0->C (current-ticks) 1.79 1.80 -(defn test-timer [] 1.81 - (flatten 1.82 - [0x3E 1.83 - 0x01 1.84 - 0xE0 1.85 - 0x06 ;; set TMA to 0 1.86 - 1.87 - 0x3E 1.88 - (Integer/parseInt "00000100" 2) 1.89 - 0xE0 1.90 - 0x07 ;; set TAC to 16384 Hz and activate timer 1.91 - 1.92 - (repeat 1.93 - 500 1.94 - [0xF0 1.95 - 0x05])])) 1.96 - 1.97 - 1.98 (defn music-kernel [] 1.99 (flatten 1.100 [(clear-music-registers) 1.101 @@ -161,9 +177,10 @@ 1.102 0xE0 1.103 0x07 ;; set TAC to 65536 Hz and activate timer 1.104 1.105 - 0xF0 1.106 - 0x07 1.107 - 1.108 + 1.109 + 0xAF ;; initialiaze A to zero 1.110 + 1.111 + 1.112 (music-step) 1.113 0x18 1.114 (->signed-8-bit (+ (- (count (music-step))) 1.115 @@ -188,8 +205,59 @@ 1.116 0xA6 0x55 0xFF 1.117 0x00 0x00 0xFF 1.118 ]) 1.119 - 1.120 - 1.121 + 1.122 +(defn frequency-code->frequency 1.123 + [code] 1.124 + (assert (<= 0 code 2047)) 1.125 + (/ 131072 (- 2048 code))) 1.126 + 1.127 +(defn clamp [x low high] 1.128 + (cond (> x high) high 1.129 + (< x low) low 1.130 + true x)) 1.131 + 1.132 +(defn frequency->frequency-code 1.133 + [frequency] 1.134 + (clamp 1.135 + (Math/round 1.136 + (float 1.137 + (/ (- (* 2048 frequency) 131072) frequency))) 1.138 + 0x00 2048)) 1.139 + 1.140 +(defn note-codes [frequency volume duration] 1.141 + (assert (<= 0 volume 0xF)) 1.142 + (assert (<= 0 duration 0xFF)) 1.143 + (let [frequency-code 1.144 + (frequency->frequency-code frequency) 1.145 + volume&high-frequency 1.146 + (+ (bit-shift-left volume 4) 1.147 + (bit-shift-right frequency-code 8)) 1.148 + low-frequency 1.149 + (bit-and 0xFF frequency-code)] 1.150 + [volume&high-frequency 1.151 + low-frequency 1.152 + duration])) 1.153 + 1.154 +(def C4 (partial note-codes 261.63)) 1.155 +(def D4 (partial note-codes 293.66)) 1.156 +(def E4 (partial note-codes 329.63)) 1.157 +(def F4 (partial note-codes 349.23)) 1.158 +(def G4 (partial note-codes 392)) 1.159 +(def A4 (partial note-codes 440)) 1.160 +(def B4 (partial note-codes 493.88)) 1.161 +(def C5 (partial note-codes 523.3)) 1.162 + 1.163 +(def scale 1.164 + (flatten 1.165 + [(C4 0xF 0x40) 1.166 + (D4 0xF 0x40) 1.167 + (E4 0xF 0x40) 1.168 + (F4 0xF 0x40) 1.169 + (G4 0xF 0x40) 1.170 + (A4 0xF 0x40) 1.171 + (B4 0xF 0x40) 1.172 + (C5 0xF 0x40)])) 1.173 + 1.174 (defn play-music [music-bytes] 1.175 (let [program-target 0xC000 1.176 music-target 0xD000] 1.177 @@ -220,3 +288,19 @@ 1.178 (defn trippy [] 1.179 (run-moves (play-music many-notes ) (repeat 8000 []))) 1.180 1.181 +(defn test-timer [] 1.182 + (flatten 1.183 + [0x3E 1.184 + 0x01 1.185 + 0xE0 1.186 + 0x06 ;; set TMA to 0 1.187 + 1.188 + 0x3E 1.189 + (Integer/parseInt "00000100" 2) 1.190 + 0xE0 1.191 + 0x07 ;; set TAC to 16384 Hz and activate timer 1.192 + 1.193 + (repeat 1.194 + 500 1.195 + [0xF0 1.196 + 0x05])]))