; ; Octave synthesizer PIC program series ; ; OCT54ALL.ASM copyright (c) by Scott Rider 1997, all rights reserved ; ; Octave tone source:12 equally-tempered semitones in parallel. Waveform is 50% duty (square) pulse for each pitch. ; PIC uses 16MHz crystal, so use a fast PIC. ^^ ; ; 12__ ; \/2 = 1.059463094 ; ; The top octave of frequencies: ; ; C=/239 = 4186.01, B=/253 = 3951.07, A#=/268 = 3729.31, A=/284 = 3520.00 ; G#=/301 = 3322.44, G=/319 = 3135.96, F#=/338 = 2959.96, F=/358 = 2793.83, ; E=/379 = 2637.02, D#=/402 = 2489.02, D=/426 = 2349.32, C#=/451 = 2217.46 ; (C=/478 = 2093.00) ; ; This program generates the scale down 4 octaves: ; ; C3 (middle C) = 261.62Hz, B2 = 246.94Hz, A#2 = 233.08Hz ; A2 = 220.00Hz, G#2 = 207.65Hz, G2 = 196.00, F#2 = 185.00Hz ; F2 = 174.61Hz, E2 = 164.81Hz, D#2 = 155.56Hz, D2 = 146.83Hz ; C#2 = 138.59Hz, (C2 = 130.81Hz) ; ; ; The PIC16C54 as an octave divider looks like this: ; ; ________ ________ ; | \/ | ; B2 --+ RA2 RA1 +-- A#2 ; | | ; C3 --+ RA3 RA0 +-- A2 ; | | ; N/C --+ RTCC CLKI/X1 +-- \ ; | | 16MHz crystal w/33pF caps ; Tie to Vdd --+ !MCLR CLKO/X2 +-- / or 16MHz clock to CLKI ; | | ; GND --+ Vss Vdd +-- +5V ; | | ; C#2 --+ RB0 RB7 +-- G#2 ; | | ; D2 --+ RB1 RB6 +-- G2 ; | | ; D#2 --+ RB2 RB5 +-- F#2 ; | | ; E2 --+ RB3 RB4 +-- F2 ; |__________________| ; ; list p=16C54c radix dec include "pic16c54.inc" __FUSES _CP_OFF & _WDT_OFF & _HS_OSC C3 equ 60 ;31250 / 60 / 2 = 260.42 (261.62, -1.21) 0.46% B2 equ 63 ;31250 / 63 / 2 = 248.02 (246.94, +1.08) 0.43% AS2 equ 67 ;31250 / 67 / 2 = 233.21 (233.08, +0.13) 0.06% A2 equ 71 ;31250 / 71 / 2 = 220.07 (220.00, +0.07) 0.03% GS2 equ 75 ;31250 / 75 / 2 = 208.34 (207.65, +0.69) 0.33% G2 equ 80 ;31250 / 80 / 2 = 195.32 (196.00, -0.68) 0.35% FS2 equ 84 ;31250 / 84 / 2 = 186.01 (185.00, +1.01) 0.54% F2 equ 89 ;31250 / 89 / 2 = 175.56 (174.61, +0.95) 0.54% E2 equ 95 ;31250 / 93 / 2 = 164.48 (164.81, -0.73) 0.21% DS2 equ 101 ;31250 / 101 / 2 = 154.71 (155.56, -0.54) 0.55% D2 equ 107 ;31250 / 107 / 2 = 146.03 (146.83, -0.50) 0.54% CS2 equ 113 ;31250 / 113 / 2 = 138.28 (138.59, -0.31) 0.22% C3mask equ b'00001000' B2mask equ b'00000100' AS2mask equ b'00000010' A2mask equ b'00000001' GS2mask equ b'10000000' G2mask equ b'01000000' FS2mask equ b'00100000' F2mask equ b'00010000' E2mask equ b'00001000' DS2mask equ b'00000100' D2mask equ b'00000010' CS2mask equ b'00000001' tonesA equ PORTA tonesB equ PORTB cblock 0x08 C3reg B2reg AS2reg A2reg GS2reg G2reg FS2reg F2reg E2reg DS2reg D2reg CS2reg temp endc ; ; ; Main code area ; ; org 0x100 start movlw b'00000110' ;TMR0 clock = 1:128 of Fosc/4 option ;31.25KHz TMR0 @ xtal=16MHz movlw b'00000000' ;Clear tone bits movwf tonesA ; / movwf tonesB ;/ tris tonesA ;Tone bits are outputs tris tonesB ;/ movlw C3 ;Load tone period counters movwf C3reg movlw B2 movwf B2reg movlw AS2 movwf AS2reg movlw A2 movwf A2reg movlw GS2 movwf GS2reg movlw G2 movwf G2reg movlw FS2 movwf FS2reg movlw F2 movwf F2reg movlw E2 movwf E2reg movlw DS2 movwf DS2reg movlw D2 movwf D2reg movlw CS2 movwf CS2reg ; ; Main loop. TMR0 is set for 32us intervals (31,250Hz). 128 instruction ; cycles are available between successive ticks of TMR0 to check tone ; counters and toggle tone outputs. Higher pitches are possible; the ; tradeoff being fewer tones can be implemented per PIC. See other ; versions of the PIC octave divider in this series. ; main movf TMR0,W ;wait for clock tick movwf temp tick movf TMR0,W xorwf temp,W btfsc STATUS,Z goto tick ;/ m_c3 decfsz C3reg,F ;Check each tone counter... goto m_b2 ; ; C3 ready to toggle ; movf tonesA,W xorlw C3mask ;toggle C3 tone pin movwf tonesA movlw C3 movwf C3reg m_b2 decfsz B2reg,F goto m_as2 ; ; B2 ready to toggle ; movf tonesA,W xorlw B2mask ;toggle B2 tone pin movwf tonesA movlw B2 movwf B2reg m_as2 decfsz AS2reg,F goto m_a2 ; ; A sharp 2 ready to toggle ; movf tonesA,W xorlw AS2mask ;toggle AS2 tone pin movwf tonesA movlw AS2 movwf AS2reg m_a2 decfsz A2reg,F goto m_gs2 ; ; A2 ready to toggle ; movf tonesA,W xorlw A2mask ;toggle A2 tone pin movwf tonesA movlw A2 movwf A2reg m_gs2 decfsz GS2reg,F goto m_g2 ; ; G sharp 2 ready to toggle ; movf tonesB,W xorlw GS2mask ;toggle GS2 tone pin movwf tonesB movlw GS2 movwf GS2reg m_g2 decfsz G2reg,F goto m_fs2 ; ; G2 ready to toggle ; movf tonesB,W xorlw G2mask ;toggle G2 tone pin movwf tonesB movlw G2 movwf G2reg m_fs2 decfsz FS2reg,F goto m_f2 ; ; F sharp 2 ready to toggle ; movf tonesB,W xorlw FS2mask ;toggle FS3 tone pin movwf tonesB movlw FS2 movwf FS2reg m_f2 decfsz F2reg,F goto m_e2 ; ; F2 ready to toggle ; movf tonesB,W xorlw F2mask ;toggle F2 tone pin movwf tonesB movlw F2 movwf F2reg m_e2 decfsz E2reg,F goto m_ds2 ; ; E2 ready to toggle ; movf tonesB,W xorlw E2mask ;toggle E2 tone pin movwf tonesB movlw E2 movwf E2reg m_ds2 decfsz DS2reg,F goto m_d2 ; ; D sharp 2 ready to toggle ; movf tonesB,W xorlw DS2mask ;toggle DS2 tone pin movwf tonesB movlw DS2 movwf DS2reg m_d2 decfsz D2reg,F goto m_cs2 ; ; D2 ready to toggle ; movf tonesB,W xorlw D2mask ;toggle D2 tone pin movwf tonesB movlw D2 movwf D2reg m_cs2 decfsz CS2reg,F goto main ; ; C sharp 2 ready to toggle ; movf tonesB,W xorlw CS2mask ;toggle CS2 tone pin movwf tonesB movlw CS2 movwf CS2reg goto main ;Worst case=86 cycles ; ; Reset vector, 0x1FF ; org 0x1FF goto start end