Jump to content
43oh

12 voice polyphonic wavetable synth with G2211


Recommended Posts

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.

Link to post
Share on other sites
  • 1 year later...
  • 2 weeks later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...