oPossum 1,083 Posted June 11, 2011 Share Posted June 11, 2011 PWM audio output on P1.6. Uses NCO with 16 or 32 bit precision. No interpolation due to lack of hardware multiplier on G2211. ; synth.asm .cdecls C, LIST, "msp430g2211.h" smplrt .equ 38400 ; Sample rate ph32 .equ 0 ; Use 32 bit phase .text .global set_tick .global get_tick .global synth_init .global set_note .bss tick, 2 .if ph32 .bss phase_inc, 4 * 12 ; Phase increment LSW/MSW (from note table) .bss phase_acc, 4 * 12 ; Phase accumulator LSW/MSW .else .bss phase_inc, 2 * 12 ; Phase increment (from note table) .bss phase_acc, 2 * 12 ; Phase accumulator .endif set_tick mov R12, &tick ret get_tick mov &tick, R12 ret synth_init mov #0x0210, &TACTL ; Timer A config: SMCLK, count up ;mov #511, &TACCR0 ; Setup Timer A period for 31250 sps mov #415, &TACCR0 ; Setup Timer A period for 38400 sps mov #256, &TACCR1 ; Setup Timer A compare mov #0x00E0, &TACCTL1 ; Setup Timer A reset/set output mode ; mov #phase_inc, R12 ; Clear all phase inc and accum .if ph32 ; mov #4 * 12, R14 ; Word count .else ; mov #2 * 12, R14 ; Word count .endif ; clr 0(R12) ; Clear word incd R12 ; Next word dec R14 ; Dec word count jne $ - 8 ; Loop until all words done... ; eint ; Enable interupts bis #0x0010, &TACCTL1 ; Enable PWM interupt ret synth_isr push R4 push R5 push R6 push R7 push R8 push R9 mov #sine, R4 ; Get wavetable pointer mov #phase_inc, R5 ; Setup phase increment pointer .if ph32 ; mov #phase_acc + 2, R6 ; Setup phase accumulator pointer .else ; mov #phase_acc, R6 ; Setup phase accumulator pointer .endif ; clr R7 ; Clear sample accumulator mov #12, R8 ; Setup voice count voice_loop ; mov @R6, R9 ; Get phase acc (MSW) swpb R9 ; Swap MSB/LSB mov.b R9, R9 ; Clear MSB add R4, R9 ; Add wavetable pointer mov.b @R9, R9 ; Get wave sample add R9, R7 ; Update sample .if ph32 ; add @R5+, -2(R6) ; Update phase acc addc @R5+, 0(R6) ; add #4, R6 ; Increment phase acc pointer .else ; add @R5+, 0(R6) ; Update phase acc incd R6 ; Increment phase acc pointer .endif ; dec R8 ; Dec voice count jne voice_loop ; Next voice... ; rra R7 ; rra R7 ; rra R7 ; add #16, R7 ; mov R7, &TACCR1 ; Output sample ; dec &tick ; jc $ + 6 ; clr &tick ; ; bic #0x01, &TACCTL1 ; ; pop R9 pop R8 pop R7 pop R6 pop R5 pop R4 reti set_note clr R14 ; Clear octave count cmp #128, R12 ; jhs note_off ; tst_note ; cmp #116, R12 ; Within note table? jge get_pi ; Yes... inc R14 ; Inc octave count add #12, R12 ; Add octave to note jmp tst_note ; Check again... get_pi ; Get phase increment sub #116, R12 ; Adjust for first note in table rla R12 ; MIDI note * 2 .if ph32 ; rla R12 ; MIDI note * 2 (* 4 total) add #notes, R12 ; Add note table pointer mov @R12+, R15 ; Get LSW .else ; add #notes, R12 ; Add note table pointer .endif ; mov @R12, R12 ; Get MSW tst R14 ; Shifting required? jeq set_phase ; No... shift_phase ; rra R12 ; Shift phase inc .if ph32 ; rrc R15 ; .endif ; dec R14 ; Dec octave count jne shift_phase ; Repeat until zero... set_phase ; rla R13 ; Voice * 2 .if ph32 ; rla R13 ; Voice * 2 (* 4 total) add #phase_inc, R13 ; Add phase inc pointer mov R15, 0(R13) ; Set phase inc mov R12, 2(R13) ; .else ; add #phase_inc, R13 ; Add phase inc pointer mov R12, 0(R13) ; Set phase inc .endif ; ret ; Return ; note_off ; rla R13 ; Voice * 2 .if ph32 ; rla R13 ; Voice * 2 (* 4 total) .endif ; mov R13, R12 ; Copy add #phase_inc, R12 ; Phase inc pointer add #phase_acc, R13 ; Phase accum pointer clr 0(R12) ; Clear phase inc clr 0(R13) ; Clear phase accum .if ph32 ; clr 2(R12) ; clr 2(R13) ; .endif ; ret ; Return ; ; notes ; MIDI Note Frequency .if smplrt == 31250 ; 31250 sps .if ph32 ; .long 913264688 ; 116 G#8 6644.875 .long 967570232 ; 117 A8 7040.000 .long 1025104952 ; 118 A#8 7458.620 .long 1086060865 ; 119 B8 7902.133 .long 1150641405 ; 120 C9 8372.018 .long 1219062103 ; 121 C#9 8869.844 .long 1291551308 ; 122 D9 9397.273 .long 1368350945 ; 123 D#9 9956.063 .long 1449717327 ; 124 E9 10548.082 .long 1535922005 ; 125 F9 11175.303 .long 1627252680 ; 126 F#9 11839.822 .long 1724014160 ; 127 G9 12543.854 .else ; .word 13935 ; 116 G#8 6644.726 .word 14764 ; 117 A8 7040.024 .word 15642 ; 118 A#8 7458.687 .word 16572 ; 119 B8 7902.145 .word 17557 ; 120 C9 8371.830 .word 18601 ; 121 C#9 8869.648 .word 19708 ; 122 D9 9397.507 .word 20879 ; 123 D#9 9955.883 .word 22121 ; 124 E9 10548.115 .word 23436 ; 125 F9 11175.156 .word 24830 ; 126 F#9 11839.867 .word 26306 ; 127 G9 12543.678 .endif ; .endif ; ; .if smplrt == 38400 ; 38400 sps .if ph32 ; .word 743216706 ; 116 G#8 6644.875 .word 787410671 ; 117 A8 7040.000 .word 834232546 ; 118 A#8 7458.620 .word 883838595 ; 119 B8 7902.133 .word 936394372 ; 120 C9 8372.018 .word 992075279 ; 121 C#9 8869.844 .word 1051067145 ; 122 D9 9397.273 .word 1113566850 ; 123 D#9 9956.063 .word 1179782981 ; 124 E9 10548.082 .word 1249936527 ; 125 F9 11175.303 .word 1324261621 ; 126 F#9 11839.822 .word 1403006315 ; 127 G9 12543.854 .else ; .word 11341 ; 116 G#8 6645.117 .word 12015 ; 117 A8 7040.039 .word 12729 ; 118 A#8 7458.398 .word 13486 ; 119 B8 7901.953 .word 14288 ; 120 C9 8371.875 .word 15138 ; 121 C#9 8869.922 .word 16038 ; 122 D9 9397.266 .word 16992 ; 123 D#9 9956.250 .word 18002 ; 124 E9 10548.047 .word 19073 ; 125 F9 11175.586 .word 20207 ; 126 F#9 11840.039 .word 21408 ; 127 G9 12543.750 .endif ; .endif ; sine .byte 128 .byte 131 .byte 134 .byte 137 .byte 140 .byte 144 .byte 147 .byte 150 .byte 153 .byte 156 .byte 159 .byte 162 .byte 165 .byte 168 .byte 171 .byte 174 .byte 177 .byte 179 .byte 182 .byte 185 .byte 188 .byte 191 .byte 193 .byte 196 .byte 199 .byte 201 .byte 204 .byte 206 .byte 209 .byte 211 .byte 213 .byte 216 .byte 218 .byte 220 .byte 222 .byte 224 .byte 226 .byte 228 .byte 230 .byte 232 .byte 234 .byte 235 .byte 237 .byte 239 .byte 240 .byte 241 .byte 243 .byte 244 .byte 245 .byte 246 .byte 248 .byte 249 .byte 250 .byte 250 .byte 251 .byte 252 .byte 253 .byte 253 .byte 254 .byte 254 .byte 254 .byte 255 .byte 255 .byte 255 .byte 255 .byte 255 .byte 255 .byte 255 .byte 254 .byte 254 .byte 254 .byte 253 .byte 253 .byte 252 .byte 251 .byte 250 .byte 250 .byte 249 .byte 248 .byte 246 .byte 245 .byte 244 .byte 243 .byte 241 .byte 240 .byte 239 .byte 237 .byte 235 .byte 234 .byte 232 .byte 230 .byte 228 .byte 226 .byte 224 .byte 222 .byte 220 .byte 218 .byte 216 .byte 213 .byte 211 .byte 209 .byte 206 .byte 204 .byte 201 .byte 199 .byte 196 .byte 193 .byte 191 .byte 188 .byte 185 .byte 182 .byte 179 .byte 177 .byte 174 .byte 171 .byte 168 .byte 165 .byte 162 .byte 159 .byte 156 .byte 153 .byte 150 .byte 147 .byte 144 .byte 140 .byte 137 .byte 134 .byte 131 .byte 128 .byte 125 .byte 122 .byte 119 .byte 116 .byte 112 .byte 109 .byte 106 .byte 103 .byte 100 .byte 97 .byte 94 .byte 91 .byte 88 .byte 85 .byte 82 .byte 79 .byte 77 .byte 74 .byte 71 .byte 68 .byte 65 .byte 63 .byte 60 .byte 57 .byte 55 .byte 52 .byte 50 .byte 47 .byte 45 .byte 43 .byte 40 .byte 38 .byte 36 .byte 34 .byte 32 .byte 30 .byte 28 .byte 26 .byte 24 .byte 22 .byte 21 .byte 19 .byte 17 .byte 16 .byte 15 .byte 13 .byte 12 .byte 11 .byte 10 .byte 8 .byte 7 .byte 6 .byte 6 .byte 5 .byte 4 .byte 3 .byte 3 .byte 2 .byte 2 .byte 2 .byte 1 .byte 1 .byte 1 .byte 1 .byte 1 .byte 1 .byte 1 .byte 2 .byte 2 .byte 2 .byte 3 .byte 3 .byte 4 .byte 5 .byte 6 .byte 6 .byte 7 .byte 8 .byte 10 .byte 11 .byte 12 .byte 13 .byte 15 .byte 16 .byte 17 .byte 19 .byte 21 .byte 22 .byte 24 .byte 26 .byte 28 .byte 30 .byte 32 .byte 34 .byte 36 .byte 38 .byte 40 .byte 43 .byte 45 .byte 47 .byte 50 .byte 52 .byte 55 .byte 57 .byte 60 .byte 63 .byte 65 .byte 68 .byte 71 .byte 74 .byte 77 .byte 79 .byte 82 .byte 85 .byte 88 .byte 91 .byte 94 .byte 97 .byte 100 .byte 103 .byte 106 .byte 109 .byte 112 .byte 116 .byte 119 .byte 122 .byte 125 ; Interrupt Vectors .sect ".int08" ; TACCR1 CCIFG, TAIFG .short synth_isr ; ; .end ; Some code to test it... // main.c #include "msp430g2211.h" void set_tick(unsigned); unsigned get_tick(void); void synth_init(); void set_note(int, unsigned); void main(void) { unsigned n; WDTCTL = WDTPW + WDTHOLD; BCSCTL1 = XT2OFF + 15; P1DIR = 0xF2; // I/O assignment P1REN = 0x0D; // Pull up resistor for switch and Rxd P1OUT = 0x0F; // Pull up, serial idle high P1SEL = 0x50; // Enable Timer A output, SMCLK output synth_init(); #if 0 set_note(33, 0); // A1 55 Hz set_note(45, 1); // A2 110 Hz set_note(57, 2); // A3 220 Hz set_note(69, 3); // A4 440 Hz set_note(81, 4); // A5 880 Hz set_note(93, 5); // A6 1760 Hz set_note(105, 6); // A7 3520 Hz set_note(117, 7); // A8 7040 Hz #endif #if 0 set_note(69, 0); // A4 440 Hz set_note(70, 1); // set_note(71, 2); // set_note(72, 3); // set_note(73, 4); // set_note(74, 5); // set_note(75, 6); // set_note(76, 7); // set_note(77, 8); // set_note(78, 9); // set_note(79, 10); // set_note(80, 11); // #endif #if 1 n = 57; for(; { set_note(0x7F & n++, 0); set_tick(5000); while(get_tick()); set_note(-1, 0); set_tick(1000); while(get_tick()); } #endif for(;; } Working on MIDI support so it can play music. jsolarski, NatureTM, RobG and 2 others 5 Quote Link to post Share on other sites
artifus 16 Posted September 23, 2012 Share Posted September 23, 2012 this looks interesting. assembly is even more beyond me than c at the mo, though. was this just swallowed up by your fraunchpad synth project or has there been any progress or development, particularly with the 2211 and/or 2231? also: http://rcarduino.blogspot.co.uk/2012/08/the-must-build-arduino-project-illutron.html Quote Link to post Share on other sites
lastaid 15 Posted September 23, 2012 Share Posted September 23, 2012 For some reason i cannot get it to work, the only thing i hear is a single frequency. i am using a piezo on gnd and port 1.6. thanks, lastaid Quote Link to post Share on other sites
artifus 16 Posted October 4, 2012 Share Posted October 4, 2012 pretty much the same result here but didn't play with it long enough to rule out user error or make any other progress at the time. *thought* is a dac presumed/required? Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.