;Lorin Parker (Copyright 2005, 2006) ;Insanium 2.0 alpha ; 18f4520 ; Creative Commons Liscence -- Some rights reserved. ; ;Feel free to redistribute, edit, or use this code. However, commercial or "for profit" or "for sale" applications must be approved by the original author. ;Modifying and reusing the code is cool, as long as it is shared-alike as stated by Creative Commons license (kept open, free and non-commercial). ; ;Please share any improvements or revisions with Lorin Parker. He wants people to have fun with this, and make cool instruments to share with the community! ;He also could stand to learn more himself... ; ; This project is created by Lorin Edwin Parker ; http://music.calarts.edu/~lorinp/ ; ; Some portions of this code come from the PICLIST code repository at www.piclist.com LIST P=18F4520 #include ; File contains addresses for register and bit names cblock F1H F1L D1 D2 D3 WAVE MODE NumH NumL TempStatus Previous Tens_Ones TenK Thou Hund Tens ; Some of these aren't needed anymore, but I haven't bothered deleting them Ones endc #define Button PORTB,0 ; Define the "Button" Pin ;#define DebugT ; Use "Debug" To Reduce Polling Loops #define TEMP 0x0 #define PREVB 0x0 #define PREVCVA 0x0 #define char_hi 0x0 #define CHAR_LO 0x0 #define BUFFER 0x0 ;************************************************************ ; reset and interrupt vectors org 0x000000 ; Reset Vector Address goto Start org 0x00008 ; Interrupt Vector Address nop goto ISR ;************************************************************ ; program code starts here org 0x0002c nop Start clrf PORTA movlw 0xFF movwf TRISA clrf PORTB ; clear all bits of PORTB movlw 0xFF ;Port B are inputs movwf TRISB ; Set PORTB as inputs clrf PORTE movlw b'00000111' movf TRISE ;NOTE --PORTC is set and TRIS in INITSER routine to be inputs EXCEPT TX pin! call InitializeAD ; configure A/D module call InitSer bcf INTCON,TMR0IF ; clear the overflow bit bsf INTCON,GIE ; enable global interrupt bsf INTCON,TMR0IE ; enable timer0 interrupts Timer0 movlw b'11000111' ;on, 8-bit, 1:256 prescale -- about 26 ms till overflow movwf T0CON bsf T0CON,TMR0ON ; enable the timer ; call InitSCP Main btfss PORTB,6 goto Main goto SCP nop SCP call InitSCP bsf ADCON2,7 ;Right justify the result of ADC clrf ADCON0 Control ;begin ADC control of synth mode (SCP) ; Get AD0 value Adc0 bsf ADCON0,ADON call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert Send0 movlw A'0' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Thou, w movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc1 bsf ADCON0,CHS0 ;switch to AN1 (001) bsf ADCON0,ADON call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert Send1 movlw A'1' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Thou, w movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc2 bcf ADCON0,CHS0 ;switch to AN2 (010) bsf ADCON0,CHS1 bsf ADCON0,ADON call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert Send2 movlw A'2' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Thou, w movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc3 movlw b'00001101' movwf ADCON0 call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert Send3 movlw A'3' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Thou, w movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc4 bcf ADCON0,CHS0 ;switch to AN4 (100) bcf ADCON0,CHS1 ; bsf ADCON0,CHS2 ; bsf ADCON0,ADON call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert Send4 movlw A'4' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Thou, w movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc5 movlw b'00010101' movwf ADCON0 call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert Send5 movlw A'5' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Thou, w movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc6 movlw b'00011001' movwf ADCON0 bcf ADCON2,7 ;Left justify the result so we can drop 2 LSBs call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert256 Send6 movlw A'6' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc7 movlw b'00011101' movwf ADCON0 call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert32 Send7 movlw A'B' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc8 movlw b'00100001' movwf ADCON0 call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert32 Send8 movlw A'C' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll movlw A'D' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc9 movlw b'00100101' movwf ADCON0 call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert32 Send9 movlw A'1' movwf TXREG call TxPoll movlw A'4' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll movlw A'1' movwf TXREG call TxPoll movlw A'5' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Goback ;set everything back and loop in synth mode bsf ADCON2,7 ;Right justify the result again clrf ADCON0 goto Control ;=============================================================== Test btfsc ADCON0,GO ;poll adc - is it done? goto Test ;no ; bcf PIR1,ADIF ;yes return Convert clrf Thous clrf Hund clrf Tens clrf Ones clrf Tens_Ones movf ADRESL,W movwf NumL movf ADRESH,W movwf NumH call Thous call bin2dec999fast movf Tens_Ones,W call BinToASCII movwf CHAR_LO movlw 0x30 addwf Hund return Convert256 clrf Hund clrf Tens clrf Ones clrf Tens_Ones movf ADRESH,W movwf NumL clrf NumH call bin2dec999fast movf Tens_Ones,W call BinToASCII movwf CHAR_LO movlw 0x30 addwf Hund return Convert32 clrf Hund clrf Tens clrf Ones clrf Tens_Ones movf ADRESH,W movwf NumL rrcf NumL bcf STATUS,C rrcf NumL bcf STATUS,C rrcf NumL bcf STATUS,C movlw .6 sublw NumL ;offset the volume a bit bcf STATUS,Z ; just in case clrf NumH call bin2dec999fast movf Tens_Ones,W call BinToASCII movwf CHAR_LO return ;************************************************************ ; InitializeAD - initializes and sets up the A/D hardware. ; Select AN0 to AN3 as analog inputs, RC clock, and read AN0. InitializeAD ; bsf ADCON0,0 ; ADC on! clrf ADCON0 movlw b'00000101' clrf ADCON1 ; Port A pins are all ADC and voltage references are VSS VDD AN10,AN11,AN12 are DIGITAL movlw B'10101101' ; Select RC osc, 101 = 12 TAD 101 = Fosc/16 movwf ADCON2 ; right justified result bcf PIR1,ADIF bcf PIE1,ADIE return ;************************************************************ ;Initialize the TX RX serial InitSer ; initialize the serial! movlw b'01001000' movwf BAUDCON movlw .129 ;.129 16 bit high mode movwf SPBRG clrf SPBRGH bsf TXSTA,BRGH ; high baud clrf PORTC movlw b'10111111' movf TRISC ; bcf TRISC,6 ; clear RC6 ; bsf TRISC,7 ; set RC7 bcf TXSTA,SYNC ; transmit bit bsf RCSTA,SPEN ; enable receive bsf TXSTA,TXEN ; transmit bit ;bsf RCSTA,CREN ; enable continuous reception Return InitSCP ;call TxPoll movlw 5Ch movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw '8' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll return TxPoll btfss TXSTA,TRMT ;poll trmt - has it sent? goto TxPoll ;no nop ;yes return ;************************************************************ ; This is used to allow the A/D time to sample the input ; (acquisition time). SetupDelay movlw .30 ; Delay time movwf TEMP SD decfsz TEMP, F ; Delay loop goto SD return Delay ;17499991 cycles movlw 0xff movwf D1 movlw 0x10 movwf D2 movlw 0x00 movwf D3 Delay_0 decfsz D1, f goto $-2 decfsz D2, f goto $-2 decfsz D3, f goto Delay_0 ;4 cycles (including call) return bin2dec999fast ; convert ; add b[3:0] + b[7:4] for ones swapf NumL, w ;Add the upper and lower nibbles addwf NumL, w ;to get the one's digit andlw 0x0F ; if sum is bigger than 15 (DC is set), add 16 to BCD result btfsc STATUS,1 ;Go through a binary to bcd addlw 0x16 ;conversion for just the one's ; if lower digit overflowed again, add 16 again btfsc STATUS,1 ;digit addlw 0x06 ; make sure the lower digit is in 0..9 range. If not, do BCD ; correction (add 6) addlw 0x06 btfss STATUS,1 addlw -0x06 ; add now 5*b[4] to ones accumulator and b[4] to tens, doing the ; BCD correction at the same time btfsc NumL, 4 ;bit 4 is a special case addlw 0x16 - 1 + 0x6 BTFSS STATUS,1 addlw -0x06 ; here we have converted already bits 0 to 4: ; ones = b[3:0] + b[7:4] + b[9:8] + 5*b[4] + 5*b[8] ; --------------- ------- ; tens = 2*b[6:5] + b[4] + b[6:5] + 2*b[7] + 5*b[8] + b[9] ; ---- ; hund = b[9:7] + b[9] ; now just test bits 5 to 7 and add their decimal weights to ; tens only (bit 7 also affects hundreds). We can add maximum ; 11 to tens digit here, so it will be less than 16 and not overflow. ;now adjust the ten's digit btfsc NumL, 5 ;2^5 = 32, so add 3 to the ten's addlw 0x30 ;digit if bit 5 is set btfsc NumL, 6 ;2^6 = 64, so add 6 addlw 0x60 ;if bit 6 is set btfsc NumL, 7 ;2^7 = 128, so add 2 (the ten's addlw 0x20 ;digit) if bit 7 is set ; do decimal correction for tens and propagate carry to hundreds addlw 0x60 ;convert the ten's digit to bcd clrf Hund rlcf Hund, f ;if there's a carry, then the input btfss Hund, 0 ;was greater than 99. addlw -0x60 movwf Tens_Ones ; Here we are done with bits 5 to 7 (except bit 7 for hundreds): ; ones = b[3:0] + b[7:4] + b[9:8] + 5*b[4] + 5*b[8] ; --------------- ------- ; tens = 2*b[6:5] + b[4] + b[6:5] + 2*b[7] + 5*b[8] + b[9] ; -------- ---- ------ ------ ; hund = b[9:7] + b[9] ; test bit 8, and add what it contributes to ones and tens movlw 0x66 ;2^8 = 256, so add 0x56 to Tens_Ones btfsc NumH, 0 movlw 0x56 + 0x66 ;add 0x66 for decimal adjust addwf Tens_Ones, f ; do decimal correction movff STATUS,TempStatus ; Save status so incf doesn't mess up C and DC BTFSC STATUS,C incf Hund, f movff TempStatus,STATUS ; Restore the status movlw 0h BTFSS STATUS,0 iorlw 0x60 BTFSS STATUS,1 iorlw 0x06 subwf Tens_Ones, f ; Here we are done with bit 8: ; ones = b[3:0] + b[7:4] + 2*b[9] + b[8] + 5*b[4] + 5*b[8] ; --------------- ----- ------- ------ ; tens = 2*b[6:5] + b[4] + b[6:5] + 2*b[7] + 5*b[8] + b[9] ; -------- ---- ------ ------ ------ ; hund = b[9:7] + b[9] ; test bit 9 (it adds 2 to ones, 1 to tens, and 5 to hundreds), ; but ignore hundreds yet movlw 0x66 ;2^9 = 512, so add 0x12 to Tens_Ones btfsc NumH, 1 movlw 0x12 + 0x66 addwf Tens_Ones, f movff STATUS, TempStatus ; Save so incf doesn't mess up C and DC BTFSC STATUS,C incf Hund, f movff TempStatus,STATUS ; Restore saved status movlw 0h BTFSS STATUS,0 iorlw 0x60 BTFSS STATUS,1 iorlw 0x06 subwf Tens_Ones, f ; Now we have a ready result for ones and tens: ; ones = b[3:0] + b[7:4] + 2*b[9] + b[8] + 5*b[4] + 5*b[8] ; --------------- ------ ----- ------- ------ ; tens = 2*b[6:5] + b[4] + b[6:5] + 2*b[7] + 5*b[8] + b[9] ; -------- ---- ------ ------ ------ ----- ; hund = b[9:7] + b[9] ; now just test bits 7, 8, and 9 and add their share to hundreds ; (without any BCD correction, because we assume input value is ; between 0 and 999, so hundreds can't be more than 9) ; btfsc NumL, 7 ;finish with hundreds ; incf Hund, f ; movlw 2 ; btfsc NumH, 0 ; addwf Hund, f ; movlw 5 ; btfsc NumH, 1 ; addwf Hund, f ;That's it! ;Wait, let's optimize the last few lines... ; hund = b[9:7] + b[9] rlcf NumL, w ; copy bit 7 to carry rlcf NumH, w ; load w with bits 9 to 7 btfsc NumH, 1 ; add b[9] addlw 1 ; addwf Hund, f ; add it to hundreds movlw .10 cpfslt Hund ;If Hund is greater than 10 make it 9 to limit numbers to 999 call Cutoff return Thous clrf Thou btfsc NumH,3 ;Number is greater than 2047! goto two ;Thou is now 2 btfsc NumH,2 goto one btfss NumH,1 return btfss NumH,0 return ;Number is greater than 767 and thus worth our time movlw 0xE7 cpfslt NumL ;if NumH:NumL is > 999 then goto one ;thou is 1 zero movlw '0' movwf Thou return one movlw 0x07 cpfslt NumH goto mtwo ;could be >2000 movlw '1' movwf Thou bcf NumH,2 ; condition it for the binary to BCD calc return two movlw '2' movwf Thou bcf NumH,3 bcf NumH,2 ; condition it for the binary to BCD calc return mtwo movlw 0xE7 cpfslt NumL ;if greater than 7:CF (1,999) goto two goto two movlw '1' movwf Thou bcf NumH,2 ; condition it for the binary to BCD calc return Cutoff movlw .0 movwf Hund return BinToASCII movwf char_hi ; save byte temporarily swapf char_hi,W andlw 0x0F ; mask out top nibble, preserv low nibble addlw 0x30 ; then finally add 58 to get 'proper' ascii movwf Tens movf char_hi,W andlw 0x0F ; mask out top nibble, preserv low nibble addlw 0x30 ; then finally add 58 to get 'proper' ascii movwf Ones return Inchi incf NumH clrf NumL bcf STATUS, Z return Talk ;Get it to say 20, 96, 21, 114, 22, 88, 23, 5, 183, 7, 159, 146, 164, 147, 151, 145, 176 in decimal movlw .20 movwf TXREG call TxPoll movlw .96 movwf TXREG call TxPoll movlw .21 movwf TXREG call TxPoll movlw .114 movwf TXREG call TxPoll movlw .22 movwf TXREG call TxPoll movlw .88 movwf TXREG call TxPoll movlw .23 movwf TXREG call TxPoll movlw .5 movwf TXREG call TxPoll movlw .183 movwf TXREG call TxPoll movlw .7 movwf TXREG call TxPoll movlw .159 movwf TXREG call TxPoll movlw .146 movwf TXREG call TxPoll movlw .164 movwf TXREG call TxPoll movlw .147 movwf TXREG call TxPoll movlw .151 movwf TXREG call TxPoll movlw .145 movwf TXREG call TxPoll movlw .176 movwf TXREG call TxPoll DelayBig call Delay call Delay call Delay return ;==================================================================== ISR ; Interrupt service routine! btfss INTCON,TMR0IF ;did timer0 overflow? retfie ;no? go home! bcf INTCON,TMR0IF ; clear it Check_buttons ;Check the momentary buttons on port B ; movlw 0x00 ; cpfseq PORTB ; Compare portB with 0 call Button_scan exit retfie ; if equal to zero Button_scan btfsc PORTC, 0 ;if 0 then skip call Square btfsc PORTC, 1 call Triangle btfsc PORTC, 2 call Sine btfsc PORTC, 3 call Saw btfsc PORTB, 7 call None btfsc PORTB, 5 goto Softreset ; btfsc PORTB, 6 ; obsolete ; btg MODE, 6 ; btfsc PORTD, 5 ; call Tweak retfie Square movlw 'R' movwf TXREG call TxPoll movlw '8' ;Send ASCII 255 to speakjet for square wave on. movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '2' movwf TXREG call TxPoll movlw '5' movwf TXREG call TxPoll movlw '5' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll BSF MODE,0 BCF MODE,1 BCF MODE,2 BCF MODE,3 BCF MODE,4 ;indicate Square in MODE for LEDs. return Triangle movlw 'R' movwf TXREG call TxPoll movlw '8' ;Send ASCII 254 to speakjet for triangle wave on. movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '2' movwf TXREG call TxPoll movlw '5' movwf TXREG call TxPoll movlw '4' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll BCF MODE,0 BSF MODE,1 BCF MODE,2 BCF MODE,3 BCF MODE,4 ;indicate Triangle in MODE for LEDs. return Sine movlw 'R' movwf TXREG call TxPoll movlw '8' ;Send ASCII 253 to speakjet for sine wave on. movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '2' movwf TXREG call TxPoll movlw '5' movwf TXREG call TxPoll movlw '3' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll BCF MODE,0 BCF MODE,1 BSF MODE,2 BCF MODE,3 BCF MODE,4 ;indicate Square in MODE for LEDs. return Saw movlw 'R' movwf TXREG call TxPoll movlw '8' ;Send ASCII 252 to speakjet for saw wave on. movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '2' movwf TXREG call TxPoll movlw '5' movwf TXREG call TxPoll movlw '2' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll BCF MODE,0 BCF MODE,1 BCF MODE,2 BSF MODE,3 BCF MODE,4 ;indicate Saw in MODE for LEDs. return None movlw 'R' movwf TXREG call TxPoll movlw '8' ;Send ASCII 0 to speakjet for no modulation movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll BCF MODE,0 BCF MODE,1 BCF MODE,2 BCF MODE,3 BSF MODE,4 ;indicate none in MODE for LEDs. return Softreset movlw 'R' movwf TXREG call TxPoll movlw 'W' ;Send ASCII to reset via software. movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll clrf MODE ;reset MODE reset Tweak ;squeal a little movlw 'R' movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '2' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll movlw '1' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '1' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll movlw '4' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '3' movwf TXREG call TxPoll movlw '5' movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll movlw '2' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll movlw 'B' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll movlw 'C' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll movlw 'E' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll return end ;Lorin Parker ;Insanium 2.0 alpha ; 18f4520 ; ;Get it to say 20, 96, 21, 114, 22, 88, 23, 5, 183, 7, 159, 146, 164, 147, 151, 145, 176 in decimal ; This project is created by Lorin Edwin Parker ; 8 channel ADC to RS232 output in raw formats so far... LIST P=18F4520 #include ; File contains addresses for register and bit names cblock F1H F1L D1 D2 D3 WAVE MODE NumH NumL TempStatus Previous Tens_Ones TenK Thou Hund Tens Ones endc #define Button PORTB,0 ; Define the "Button" Pin ;#define DebugT ; Use "Debug" To Reduce Polling Loops #define TEMP 0x0 #define PREVB 0x0 #define PREVCVA 0x0 #define char_hi 0x0 #define CHAR_LO 0x0 #define BUFFER 0x0 ;************************************************************ ; reset and interrupt vectors org 0x000000 ; Reset Vector Address goto Start org 0x00008 ; Interrupt Vector Address nop goto ISR ;************************************************************ ; program code starts here org 0x0002c nop Start clrf PORTA movlw 0xFF movwf TRISA clrf PORTB ; clear all bits of PORTB movlw 0xFF ;Port B are inputs movwf TRISB ; Set PORTB as inputs clrf PORTE movlw b'00000111' movf TRISE ;NOTE --PORTC is set and TRIS in INITSER routine to be inputs EXCEPT TX pin! call InitializeAD ; configure A/D module call InitSer bcf INTCON,TMR0IF ; clear the overflow bit bsf INTCON,GIE ; enable global interrupt bsf INTCON,TMR0IE ; enable timer0 interrupts Timer0 movlw b'11000111' ;on, 8-bit, 1:256 prescale -- about 26 ms till overflow movwf T0CON bsf T0CON,TMR0ON ; enable the timer ; call InitSCP Main btfss PORTB,6 goto Main goto SCP nop SCP call InitSCP bsf ADCON2,7 ;Right justify the result of ADC clrf ADCON0 Control ;begin ADC control of synth mode (SCP) ; Get AD0 value Adc0 bsf ADCON0,ADON call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert Send0 movlw A'0' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Thou, w movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc1 bsf ADCON0,CHS0 ;switch to AN1 (001) bsf ADCON0,ADON call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert Send1 movlw A'1' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Thou, w movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc2 bcf ADCON0,CHS0 ;switch to AN2 (010) bsf ADCON0,CHS1 bsf ADCON0,ADON call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert Send2 movlw A'2' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Thou, w movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc3 movlw b'00001101' movwf ADCON0 call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert Send3 movlw A'3' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Thou, w movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc4 bcf ADCON0,CHS0 ;switch to AN4 (100) bcf ADCON0,CHS1 ; bsf ADCON0,CHS2 ; bsf ADCON0,ADON call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert Send4 movlw A'4' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Thou, w movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc5 movlw b'00010101' movwf ADCON0 call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert Send5 movlw A'5' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Thou, w movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc6 movlw b'00011001' movwf ADCON0 bcf ADCON2,7 ;Left justify the result so we can drop 2 LSBs call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert256 Send6 movlw A'6' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc7 movlw b'00011101' movwf ADCON0 call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert32 Send7 movlw A'B' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc8 movlw b'00100001' movwf ADCON0 call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert32 Send8 movlw A'C' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll movlw A'D' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc9 movlw b'00100101' movwf ADCON0 call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert32 Send9 movlw A'1' movwf TXREG call TxPoll movlw A'4' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll movlw A'1' movwf TXREG call TxPoll movlw A'5' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Goback ;set everything back and loop in synth mode bsf ADCON2,7 ;Right justify the result again clrf ADCON0 goto Control ;=============================================================== Test btfsc ADCON0,GO ;poll adc - is it done? goto Test ;no ; bcf PIR1,ADIF ;yes return Convert clrf Thous clrf Hund clrf Tens clrf Ones clrf Tens_Ones movf ADRESL,W movwf NumL movf ADRESH,W movwf NumH call Thous call bin2dec999fast movf Tens_Ones,W call BinToASCII movwf CHAR_LO movlw 0x30 addwf Hund return Convert256 clrf Hund clrf Tens clrf Ones clrf Tens_Ones movf ADRESH,W movwf NumL clrf NumH call bin2dec999fast movf Tens_Ones,W call BinToASCII movwf CHAR_LO movlw 0x30 addwf Hund return Convert32 clrf Hund clrf Tens clrf Ones clrf Tens_Ones movf ADRESH,W movwf NumL rrcf NumL bcf STATUS,C rrcf NumL bcf STATUS,C rrcf NumL bcf STATUS,C movlw .6 sublw NumL ;offset the volume a bit bcf STATUS,Z ; just in case clrf NumH call bin2dec999fast movf Tens_Ones,W call BinToASCII movwf CHAR_LO return ;************************************************************ ; InitializeAD - initializes and sets up the A/D hardware. ; Select AN0 to AN3 as analog inputs, RC clock, and read AN0. InitializeAD ; bsf ADCON0,0 ; ADC on! clrf ADCON0 movlw b'00000101' clrf ADCON1 ; Port A pins are all ADC and voltage references are VSS VDD AN10,AN11,AN12 are DIGITAL movlw B'10101101' ; Select RC osc, 101 = 12 TAD 101 = Fosc/16 movwf ADCON2 ; right justified result bcf PIR1,ADIF bcf PIE1,ADIE return ;************************************************************ ;Initialize the TX RX serial InitSer ; initialize the serial! movlw b'01001000' movwf BAUDCON movlw .129 ;.129 16 bit high mode movwf SPBRG clrf SPBRGH bsf TXSTA,BRGH ; high baud clrf PORTC movlw b'10111111' movf TRISC ; bcf TRISC,6 ; clear RC6 ; bsf TRISC,7 ; set RC7 bcf TXSTA,SYNC ; transmit bit bsf RCSTA,SPEN ; enable receive bsf TXSTA,TXEN ; transmit bit ;bsf RCSTA,CREN ; enable continuous reception Return InitSCP ;call TxPoll movlw 5Ch movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw '8' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll return TxPoll btfss TXSTA,TRMT ;poll trmt - has it sent? goto TxPoll ;no nop ;yes return ;************************************************************ ; This is used to allow the A/D time to sample the input ; (acquisition time). SetupDelay movlw .30 ; Delay time movwf TEMP SD decfsz TEMP, F ; Delay loop goto SD return Delay ;17499991 cycles movlw 0xff movwf D1 movlw 0x10 movwf D2 movlw 0x00 movwf D3 Delay_0 decfsz D1, f goto $-2 decfsz D2, f goto $-2 decfsz D3, f goto Delay_0 ;4 cycles (including call) return bin2dec999fast ; convert ; add b[3:0] + b[7:4] for ones swapf NumL, w ;Add the upper and lower nibbles addwf NumL, w ;to get the one's digit andlw 0x0F ; if sum is bigger than 15 (DC is set), add 16 to BCD result btfsc STATUS,1 ;Go through a binary to bcd addlw 0x16 ;conversion for just the one's ; if lower digit overflowed again, add 16 again btfsc STATUS,1 ;digit addlw 0x06 ; make sure the lower digit is in 0..9 range. If not, do BCD ; correction (add 6) addlw 0x06 btfss STATUS,1 addlw -0x06 ; add now 5*b[4] to ones accumulator and b[4] to tens, doing the ; BCD correction at the same time btfsc NumL, 4 ;bit 4 is a special case addlw 0x16 - 1 + 0x6 BTFSS STATUS,1 addlw -0x06 ; here we have converted already bits 0 to 4: ; ones = b[3:0] + b[7:4] + b[9:8] + 5*b[4] + 5*b[8] ; --------------- ------- ; tens = 2*b[6:5] + b[4] + b[6:5] + 2*b[7] + 5*b[8] + b[9] ; ---- ; hund = b[9:7] + b[9] ; now just test bits 5 to 7 and add their decimal weights to ; tens only (bit 7 also affects hundreds). We can add maximum ; 11 to tens digit here, so it will be less than 16 and not overflow. ;now adjust the ten's digit btfsc NumL, 5 ;2^5 = 32, so add 3 to the ten's addlw 0x30 ;digit if bit 5 is set btfsc NumL, 6 ;2^6 = 64, so add 6 addlw 0x60 ;if bit 6 is set btfsc NumL, 7 ;2^7 = 128, so add 2 (the ten's addlw 0x20 ;digit) if bit 7 is set ; do decimal correction for tens and propagate carry to hundreds addlw 0x60 ;convert the ten's digit to bcd clrf Hund rlcf Hund, f ;if there's a carry, then the input btfss Hund, 0 ;was greater than 99. addlw -0x60 movwf Tens_Ones ; Here we are done with bits 5 to 7 (except bit 7 for hundreds): ; ones = b[3:0] + b[7:4] + b[9:8] + 5*b[4] + 5*b[8] ; --------------- ------- ; tens = 2*b[6:5] + b[4] + b[6:5] + 2*b[7] + 5*b[8] + b[9] ; -------- ---- ------ ------ ; hund = b[9:7] + b[9] ; test bit 8, and add what it contributes to ones and tens movlw 0x66 ;2^8 = 256, so add 0x56 to Tens_Ones btfsc NumH, 0 movlw 0x56 + 0x66 ;add 0x66 for decimal adjust addwf Tens_Ones, f ; do decimal correction movff STATUS,TempStatus ; Save status so incf doesn't mess up C and DC BTFSC STATUS,C incf Hund, f movff TempStatus,STATUS ; Restore the status movlw 0h BTFSS STATUS,0 iorlw 0x60 BTFSS STATUS,1 iorlw 0x06 subwf Tens_Ones, f ; Here we are done with bit 8: ; ones = b[3:0] + b[7:4] + 2*b[9] + b[8] + 5*b[4] + 5*b[8] ; --------------- ----- ------- ------ ; tens = 2*b[6:5] + b[4] + b[6:5] + 2*b[7] + 5*b[8] + b[9] ; -------- ---- ------ ------ ------ ; hund = b[9:7] + b[9] ; test bit 9 (it adds 2 to ones, 1 to tens, and 5 to hundreds), ; but ignore hundreds yet movlw 0x66 ;2^9 = 512, so add 0x12 to Tens_Ones btfsc NumH, 1 movlw 0x12 + 0x66 addwf Tens_Ones, f movff STATUS, TempStatus ; Save so incf doesn't mess up C and DC BTFSC STATUS,C incf Hund, f movff TempStatus,STATUS ; Restore saved status movlw 0h BTFSS STATUS,0 iorlw 0x60 BTFSS STATUS,1 iorlw 0x06 subwf Tens_Ones, f ; Now we have a ready result for ones and tens: ; ones = b[3:0] + b[7:4] + 2*b[9] + b[8] + 5*b[4] + 5*b[8] ; --------------- ------ ----- ------- ------ ; tens = 2*b[6:5] + b[4] + b[6:5] + 2*b[7] + 5*b[8] + b[9] ; -------- ---- ------ ------ ------ ----- ; hund = b[9:7] + b[9] ; now just test bits 7, 8, and 9 and add their share to hundreds ; (without any BCD correction, because we assume input value is ; between 0 and 999, so hundreds can't be more than 9) ; btfsc NumL, 7 ;finish with hundreds ; incf Hund, f ; movlw 2 ; btfsc NumH, 0 ; addwf Hund, f ; movlw 5 ; btfsc NumH, 1 ; addwf Hund, f ;That's it! ;Wait, let's optimize the last few lines... ; hund = b[9:7] + b[9] rlcf NumL, w ; copy bit 7 to carry rlcf NumH, w ; load w with bits 9 to 7 btfsc NumH, 1 ; add b[9] addlw 1 ; addwf Hund, f ; add it to hundreds movlw .10 cpfslt Hund ;If Hund is greater than 10 make it 9 to limit numbers to 999 call Cutoff return Thous clrf Thou btfsc NumH,3 ;Number is greater than 2047! goto two ;Thou is now 2 btfsc NumH,2 goto one btfss NumH,1 return btfss NumH,0 return ;Number is greater than 767 and thus worth our time movlw 0xE7 cpfslt NumL ;if NumH:NumL is > 999 then goto one ;thou is 1 zero movlw '0' movwf Thou return one movlw 0x07 cpfslt NumH goto mtwo ;could be >2000 movlw '1' movwf Thou bcf NumH,2 ; condition it for the binary to BCD calc return two movlw '2' movwf Thou bcf NumH,3 bcf NumH,2 ; condition it for the binary to BCD calc return mtwo movlw 0xE7 cpfslt NumL ;if greater than 7:CF (1,999) goto two goto two movlw '1' movwf Thou bcf NumH,2 ; condition it for the binary to BCD calc return Cutoff movlw .0 movwf Hund return BinToASCII movwf char_hi ; save byte temporarily swapf char_hi,W andlw 0x0F ; mask out top nibble, preserv low nibble addlw 0x30 ; then finally add 58 to get 'proper' ascii movwf Tens movf char_hi,W andlw 0x0F ; mask out top nibble, preserv low nibble addlw 0x30 ; then finally add 58 to get 'proper' ascii movwf Ones return Inchi incf NumH clrf NumL bcf STATUS, Z return Talk ;Get it to say 20, 96, 21, 114, 22, 88, 23, 5, 183, 7, 159, 146, 164, 147, 151, 145, 176 in decimal movlw .20 movwf TXREG call TxPoll movlw .96 movwf TXREG call TxPoll movlw .21 movwf TXREG call TxPoll movlw .114 movwf TXREG call TxPoll movlw .22 movwf TXREG call TxPoll movlw .88 movwf TXREG call TxPoll movlw .23 movwf TXREG call TxPoll movlw .5 movwf TXREG call TxPoll movlw .183 movwf TXREG call TxPoll movlw .7 movwf TXREG call TxPoll movlw .159 movwf TXREG call TxPoll movlw .146 movwf TXREG call TxPoll movlw .164 movwf TXREG call TxPoll movlw .147 movwf TXREG call TxPoll movlw .151 movwf TXREG call TxPoll movlw .145 movwf TXREG call TxPoll movlw .176 movwf TXREG call TxPoll DelayBig call Delay call Delay call Delay return ;==================================================================== ISR ; Interrupt service routine! btfss INTCON,TMR0IF ;did timer0 overflow? retfie ;no? go home! bcf INTCON,TMR0IF ; clear it Check_buttons ;Check the momentary buttons on port B ; movlw 0x00 ; cpfseq PORTB ; Compare portB with 0 call Button_scan exit retfie ; if equal to zero Button_scan btfsc PORTC, 0 ;if 0 then skip call Square btfsc PORTC, 1 call Triangle btfsc PORTC, 2 call Sine btfsc PORTC, 3 call Saw btfsc PORTB, 7 call None btfsc PORTB, 5 goto Softreset ; btfsc PORTB, 6 ; obsolete ; btg MODE, 6 ; btfsc PORTD, 5 ; call Tweak retfie Square movlw 'R' movwf TXREG call TxPoll movlw '8' ;Send ASCII 255 to speakjet for square wave on. movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '2' movwf TXREG call TxPoll movlw '5' movwf TXREG call TxPoll movlw '5' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll BSF MODE,0 BCF MODE,1 BCF MODE,2 BCF MODE,3 BCF MODE,4 ;indicate Square in MODE for LEDs. return Triangle movlw 'R' movwf TXREG call TxPoll movlw '8' ;Send ASCII 254 to speakjet for triangle wave on. movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '2' movwf TXREG call TxPoll movlw '5' movwf TXREG call TxPoll movlw '4' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll BCF MODE,0 BSF MODE,1 BCF MODE,2 BCF MODE,3 BCF MODE,4 ;indicate Triangle in MODE for LEDs. return Sine movlw 'R' movwf TXREG call TxPoll movlw '8' ;Send ASCII 253 to speakjet for sine wave on. movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '2' movwf TXREG call TxPoll movlw '5' movwf TXREG call TxPoll movlw '3' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll BCF MODE,0 BCF MODE,1 BSF MODE,2 BCF MODE,3 BCF MODE,4 ;indicate Square in MODE for LEDs. return Saw movlw 'R' movwf TXREG call TxPoll movlw '8' ;Send ASCII 252 to speakjet for saw wave on. movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '2' movwf TXREG call TxPoll movlw '5' movwf TXREG call TxPoll movlw '2' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll BCF MODE,0 BCF MODE,1 BCF MODE,2 BSF MODE,3 BCF MODE,4 ;indicate Saw in MODE for LEDs. return None movlw 'R' movwf TXREG call TxPoll movlw '8' ;Send ASCII 0 to speakjet for no modulation movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll BCF MODE,0 BCF MODE,1 BCF MODE,2 BCF MODE,3 BSF MODE,4 ;indicate none in MODE for LEDs. return Softreset movlw 'R' movwf TXREG call TxPoll movlw 'W' ;Send ASCII to reset via software. movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll clrf MODE ;reset MODE reset Tweak ;squeal a little movlw 'R' movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '2' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll movlw '1' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '1' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll movlw '4' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '3' movwf TXREG call TxPoll movlw '5' movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll movlw '2' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll movlw 'B' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll movlw 'C' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll movlw 'E' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll return end ;Lorin Parker ;Insanium 2.0 alpha ; 18f4520 ; ;Get it to say 20, 96, 21, 114, 22, 88, 23, 5, 183, 7, 159, 146, 164, 147, 151, 145, 176 in decimal ; This project is created by Lorin Edwin Parker ; 8 channel ADC to RS232 output in raw formats so far... LIST P=18F4520 #include ; File contains addresses for register and bit names cblock F1H F1L D1 D2 D3 WAVE MODE NumH NumL TempStatus Previous Tens_Ones TenK Thou Hund Tens Ones endc #define Button PORTB,0 ; Define the "Button" Pin ;#define DebugT ; Use "Debug" To Reduce Polling Loops #define TEMP 0x0 #define PREVB 0x0 #define PREVCVA 0x0 #define char_hi 0x0 #define CHAR_LO 0x0 #define BUFFER 0x0 ;************************************************************ ; reset and interrupt vectors org 0x000000 ; Reset Vector Address goto Start org 0x00008 ; Interrupt Vector Address nop goto ISR ;************************************************************ ; program code starts here org 0x0002c nop Start clrf PORTA movlw 0xFF movwf TRISA clrf PORTB ; clear all bits of PORTB movlw 0xFF ;Port B are inputs movwf TRISB ; Set PORTB as inputs clrf PORTD ;clear and set port d as inputs movwf TRISD clrf PORTE movlw b'00000111' movf TRISE call InitializeAD ; configure A/D module call InitSer bcf INTCON,TMR0IF ; clear the overflow bit bsf INTCON,GIE ; enable global interrupt bsf INTCON,TMR0IE ; enable timer0 interrupts Timer0 movlw b'11000111' ;on, 8-bit, 1:256 prescale -- about 26 ms till overflow movwf T0CON bsf T0CON,TMR0ON ; enable the timer ; call InitSCP Main btfss PORTB,6 goto Main goto SCP nop SCP call InitSCP Control ;begin ADC control of synth mode (SCP) ; Get AD0 value Adc0 bsf ADCON0,ADON call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert32 Send0 movlw A'0' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Thou, w movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc1 bsf ADCON0,CHS0 ;switch to AN1 (001) bsf ADCON0,ADON call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert Send1 movlw A'1' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Thou, w movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc2 bcf ADCON0,CHS0 ;switch to AN2 (010) bsf ADCON0,CHS1 bsf ADCON0,ADON call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert Send2 movlw A'2' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Thou, w movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc3 movlw b'00001101' movwf ADCON0 call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert Send3 movlw A'3' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Thou, w movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc4 bcf ADCON0,CHS0 ;switch to AN4 (100) bcf ADCON0,CHS1 ; bsf ADCON0,CHS2 ; bsf ADCON0,ADON call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert Send4 movlw A'4' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Thou, w movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc5 movlw b'00010101' movwf ADCON0 call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert Send5 movlw A'5' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Thou, w movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc6 movlw b'00011001' movwf ADCON0 bcf ADCON2,7 ;Left justify the result so we can drop 2 LSBs call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert256 Send6 movlw A'6' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll movlw A'1' movwf TXREG call TxPoll movlw A'5' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movlw A'2' movwf TXREG call TxPoll movlw A'1' movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc7 movlw b'00011101' movwf ADCON0 call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert32 Send7 movlw A'B' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc8 movlw b'00100001' movwf ADCON0 call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert32 Send8 movlw A'C' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll movlw A'D' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc9 movlw b'00100101' movwf ADCON0 call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert32 Send9 movlw A'1' movwf TXREG call TxPoll movlw A'4' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll movlw A'1' movwf TXREG call TxPoll movlw A'5' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Goback ;set everything back and loop in synth mode bsf ADCON2,7 ;Right justify the result again clrf ADCON0 goto Control ;=============================================================== Test btfsc ADCON0,GO ;poll adc - is it done? goto Test ;no ; bcf PIR1,ADIF ;yes return Convert clrf Thous clrf Hund clrf Tens clrf Ones clrf Tens_Ones movf ADRESL,W movwf NumL movf ADRESH,W movwf NumH call Thous call bin2dec999fast movf Tens_Ones,W call BinToASCII movwf CHAR_LO movlw 0x30 addwf Hund return Convert256 clrf Hund clrf Tens clrf Ones clrf Tens_Ones movf ADRESH,W movwf NumL clrf NumH call bin2dec999fast movf Tens_Ones,W call BinToASCII movwf CHAR_LO movlw 0x30 addwf Hund return Convert32 clrf Hund clrf Tens clrf Ones clrf Tens_Ones movf ADRESH,W movwf NumL rrcf NumL bcf STATUS,C rrcf NumL bcf STATUS,C rrcf NumL bcf STATUS,C movlw .6 sublw NumL ;offset the volume a bit bcf STATUS,Z ; just in case clrf NumH call bin2dec999fast movf Tens_Ones,W call BinToASCII movwf CHAR_LO return ;************************************************************ ; InitializeAD - initializes and sets up the A/D hardware. ; Select AN0 to AN3 as analog inputs, RC clock, and read AN0. InitializeAD ; bsf ADCON0,0 ; ADC on! clrf ADCON0 movlw b'00000101' clrf ADCON1 ; Port A pins are all ADC and voltage references are VSS VDD AN10,AN11,AN12 are DIGITAL movlw B'10101101' ; Select RC osc, 101 = 12 TAD 101 = Fosc/16 movwf ADCON2 ; right justified result bcf PIR1,ADIF bcf PIE1,ADIE return ;************************************************************ ;Initialize the TX RX serial InitSer ; initialize the serial! movlw b'01001000' movwf BAUDCON movlw .129 ;.129 16 bit high mode movwf SPBRG clrf SPBRGH bsf TXSTA,BRGH ; high baud clrf PORTC movlw b'10111111' movf TRISC ; bcf TRISC,6 ; clear RC6 ; bsf TRISC,7 ; set RC7 bcf TXSTA,SYNC ; transmit bit bsf RCSTA,SPEN ; enable receive bsf TXSTA,TXEN ; transmit bit ;bsf RCSTA,CREN ; enable continuous reception Return InitSCP ;call TxPoll movlw 5Ch movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw '8' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll return TxPoll btfss TXSTA,TRMT ;poll trmt - has it sent? goto TxPoll ;no nop ;yes return ;************************************************************ ; This is used to allow the A/D time to sample the input ; (acquisition time). SetupDelay movlw .30 ; Delay time movwf TEMP SD decfsz TEMP, F ; Delay loop goto SD return Delay ;17499991 cycles movlw 0xff movwf D1 movlw 0x10 movwf D2 movlw 0x00 movwf D3 Delay_0 decfsz D1, f goto $-2 decfsz D2, f goto $-2 decfsz D3, f goto Delay_0 ;4 cycles (including call) return bin2dec999fast ; convert ; add b[3:0] + b[7:4] for ones swapf NumL, w ;Add the upper and lower nibbles addwf NumL, w ;to get the one's digit andlw 0x0F ; if sum is bigger than 15 (DC is set), add 16 to BCD result btfsc STATUS,1 ;Go through a binary to bcd addlw 0x16 ;conversion for just the one's ; if lower digit overflowed again, add 16 again btfsc STATUS,1 ;digit addlw 0x06 ; make sure the lower digit is in 0..9 range. If not, do BCD ; correction (add 6) addlw 0x06 btfss STATUS,1 addlw -0x06 ; add now 5*b[4] to ones accumulator and b[4] to tens, doing the ; BCD correction at the same time btfsc NumL, 4 ;bit 4 is a special case addlw 0x16 - 1 + 0x6 BTFSS STATUS,1 addlw -0x06 ; here we have converted already bits 0 to 4: ; ones = b[3:0] + b[7:4] + b[9:8] + 5*b[4] + 5*b[8] ; --------------- ------- ; tens = 2*b[6:5] + b[4] + b[6:5] + 2*b[7] + 5*b[8] + b[9] ; ---- ; hund = b[9:7] + b[9] ; now just test bits 5 to 7 and add their decimal weights to ; tens only (bit 7 also affects hundreds). We can add maximum ; 11 to tens digit here, so it will be less than 16 and not overflow. ;now adjust the ten's digit btfsc NumL, 5 ;2^5 = 32, so add 3 to the ten's addlw 0x30 ;digit if bit 5 is set btfsc NumL, 6 ;2^6 = 64, so add 6 addlw 0x60 ;if bit 6 is set btfsc NumL, 7 ;2^7 = 128, so add 2 (the ten's addlw 0x20 ;digit) if bit 7 is set ; do decimal correction for tens and propagate carry to hundreds addlw 0x60 ;convert the ten's digit to bcd clrf Hund rlcf Hund, f ;if there's a carry, then the input btfss Hund, 0 ;was greater than 99. addlw -0x60 movwf Tens_Ones ; Here we are done with bits 5 to 7 (except bit 7 for hundreds): ; ones = b[3:0] + b[7:4] + b[9:8] + 5*b[4] + 5*b[8] ; --------------- ------- ; tens = 2*b[6:5] + b[4] + b[6:5] + 2*b[7] + 5*b[8] + b[9] ; -------- ---- ------ ------ ; hund = b[9:7] + b[9] ; test bit 8, and add what it contributes to ones and tens movlw 0x66 ;2^8 = 256, so add 0x56 to Tens_Ones btfsc NumH, 0 movlw 0x56 + 0x66 ;add 0x66 for decimal adjust addwf Tens_Ones, f ; do decimal correction movff STATUS,TempStatus ; Save status so incf doesn't mess up C and DC BTFSC STATUS,C incf Hund, f movff TempStatus,STATUS ; Restore the status movlw 0h BTFSS STATUS,0 iorlw 0x60 BTFSS STATUS,1 iorlw 0x06 subwf Tens_Ones, f ; Here we are done with bit 8: ; ones = b[3:0] + b[7:4] + 2*b[9] + b[8] + 5*b[4] + 5*b[8] ; --------------- ----- ------- ------ ; tens = 2*b[6:5] + b[4] + b[6:5] + 2*b[7] + 5*b[8] + b[9] ; -------- ---- ------ ------ ------ ; hund = b[9:7] + b[9] ; test bit 9 (it adds 2 to ones, 1 to tens, and 5 to hundreds), ; but ignore hundreds yet movlw 0x66 ;2^9 = 512, so add 0x12 to Tens_Ones btfsc NumH, 1 movlw 0x12 + 0x66 addwf Tens_Ones, f movff STATUS, TempStatus ; Save so incf doesn't mess up C and DC BTFSC STATUS,C incf Hund, f movff TempStatus,STATUS ; Restore saved status movlw 0h BTFSS STATUS,0 iorlw 0x60 BTFSS STATUS,1 iorlw 0x06 subwf Tens_Ones, f ; Now we have a ready result for ones and tens: ; ones = b[3:0] + b[7:4] + 2*b[9] + b[8] + 5*b[4] + 5*b[8] ; --------------- ------ ----- ------- ------ ; tens = 2*b[6:5] + b[4] + b[6:5] + 2*b[7] + 5*b[8] + b[9] ; -------- ---- ------ ------ ------ ----- ; hund = b[9:7] + b[9] ; now just test bits 7, 8, and 9 and add their share to hundreds ; (without any BCD correction, because we assume input value is ; between 0 and 999, so hundreds can't be more than 9) ; btfsc NumL, 7 ;finish with hundreds ; incf Hund, f ; movlw 2 ; btfsc NumH, 0 ; addwf Hund, f ; movlw 5 ; btfsc NumH, 1 ; addwf Hund, f ;That's it! ;Wait, let's optimize the last few lines... ; hund = b[9:7] + b[9] rlcf NumL, w ; copy bit 7 to carry rlcf NumH, w ; load w with bits 9 to 7 btfsc NumH, 1 ; add b[9] addlw 1 ; addwf Hund, f ; add it to hundreds movlw .10 cpfslt Hund ;If Hund is greater than 10 make it 9 to limit numbers to 999 call Cutoff return Thous clrf Thou btfsc NumH,3 ;Number is greater than 2047! goto two ;Thou is now 2 btfsc NumH,2 goto one btfss NumH,1 return btfss NumH,0 return ;Number is greater than 767 and thus worth our time movlw 0xE7 cpfslt NumL ;if NumH:NumL is > 999 then goto one ;thou is 1 zero movlw '0' movwf Thou return one movlw 0x07 cpfslt NumH goto mtwo ;could be >2000 movlw '1' movwf Thou bcf NumH,2 ; condition it for the binary to BCD calc return two movlw '2' movwf Thou bcf NumH,3 bcf NumH,2 ; condition it for the binary to BCD calc return mtwo movlw 0xE7 cpfslt NumL ;if greater than 7:CF (1,999) goto two goto two movlw '1' movwf Thou bcf NumH,2 ; condition it for the binary to BCD calc return Cutoff movlw .0 movwf Hund return BinToASCII movwf char_hi ; save byte temporarily swapf char_hi,W andlw 0x0F ; mask out top nibble, preserv low nibble addlw 0x30 ; then finally add 58 to get 'proper' ascii movwf Tens movf char_hi,W andlw 0x0F ; mask out top nibble, preserv low nibble addlw 0x30 ; then finally add 58 to get 'proper' ascii movwf Ones return Inchi incf NumH clrf NumL bcf STATUS, Z return Talk ;Get it to say 20, 96, 21, 114, 22, 88, 23, 5, 183, 7, 159, 146, 164, 147, 151, 145, 176 in decimal movlw .20 movwf TXREG call TxPoll movlw .96 movwf TXREG call TxPoll movlw .21 movwf TXREG call TxPoll movlw .114 movwf TXREG call TxPoll movlw .22 movwf TXREG call TxPoll movlw .88 movwf TXREG call TxPoll movlw .23 movwf TXREG call TxPoll movlw .5 movwf TXREG call TxPoll movlw .183 movwf TXREG call TxPoll movlw .7 movwf TXREG call TxPoll movlw .159 movwf TXREG call TxPoll movlw .146 movwf TXREG call TxPoll movlw .164 movwf TXREG call TxPoll movlw .147 movwf TXREG call TxPoll movlw .151 movwf TXREG call TxPoll movlw .145 movwf TXREG call TxPoll movlw .176 movwf TXREG call TxPoll DelayBig call Delay call Delay call Delay return ;==================================================================== ISR ; Interrupt service routine! btfss INTCON,TMR0IF ;did timer0 overflow? retfie ;no? go home! bcf INTCON,TMR0IF ; clear it Check_buttons ;Check the momentary buttons on port B movlw 0x00 cpfseq PORTB ; Compare portB with 0 call Button_scan exit retfie ; if equal to zero Button_scan btfsc PORTD, 4 ;if 0 then skip call Square btfsc PORTD, 5 call Triangle btfsc PORTD, 6 call Sine btfsc PORTD, 7 call Saw btfsc PORTB, 7 call None btfsc PORTB, 5 goto Softreset ; btfsc PORTB, 6 ; obsolete ; btg MODE, 6 btfsc PORTD, 5 call Tweak retfie Square movlw 'R' movwf TXREG call TxPoll movlw '8' ;Send ASCII 255 to speakjet for square wave on. movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '2' movwf TXREG call TxPoll movlw '5' movwf TXREG call TxPoll movlw '5' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll BSF MODE,0 BCF MODE,1 BCF MODE,2 BCF MODE,3 BCF MODE,4 ;indicate Square in MODE for LEDs. return Triangle movlw 'R' movwf TXREG call TxPoll movlw '8' ;Send ASCII 254 to speakjet for triangle wave on. movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '2' movwf TXREG call TxPoll movlw '5' movwf TXREG call TxPoll movlw '4' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll BCF MODE,0 BSF MODE,1 BCF MODE,2 BCF MODE,3 BCF MODE,4 ;indicate Triangle in MODE for LEDs. return Sine movlw 'R' movwf TXREG call TxPoll movlw '8' ;Send ASCII 253 to speakjet for sine wave on. movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '2' movwf TXREG call TxPoll movlw '5' movwf TXREG call TxPoll movlw '3' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll BCF MODE,0 BCF MODE,1 BSF MODE,2 BCF MODE,3 BCF MODE,4 ;indicate Square in MODE for LEDs. return Saw movlw 'R' movwf TXREG call TxPoll movlw '8' ;Send ASCII 252 to speakjet for saw wave on. movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '2' movwf TXREG call TxPoll movlw '5' movwf TXREG call TxPoll movlw '2' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll BCF MODE,0 BCF MODE,1 BCF MODE,2 BSF MODE,3 BCF MODE,4 ;indicate Saw in MODE for LEDs. return None movlw 'R' movwf TXREG call TxPoll movlw '8' ;Send ASCII 0 to speakjet for no modulation movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll BCF MODE,0 BCF MODE,1 BCF MODE,2 BCF MODE,3 BSF MODE,4 ;indicate none in MODE for LEDs. return Softreset movlw 'R' movwf TXREG call TxPoll movlw 'W' ;Send ASCII to reset via software. movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll clrf MODE ;reset MODE reset Tweak ;squeal a little movlw 'R' movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '2' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll movlw '1' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '1' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll movlw '4' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '3' movwf TXREG call TxPoll movlw '5' movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll movlw '2' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll movlw 'B' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll movlw 'C' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll movlw 'E' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll return end ;Lorin Parker ;Insanium 2.0 alpha ; 18f4520 ; ;Get it to say 20, 96, 21, 114, 22, 88, 23, 5, 183, 7, 159, 146, 164, 147, 151, 145, 176 in decimal ; This project is created by Lorin Edwin Parker ; 8 channel ADC to RS232 output in raw formats so far... LIST P=18F4520 #include ; File contains addresses for register and bit names cblock PDN F1H F1L D1 D2 D3 WAVE MODE NumH NumL TempStatus Previous Tens_Ones TenK Thou Hund Tens Ones Dlay endc #define Button PORTB,0 ; Define the "Button" Pin ;#define DebugT ; Use "Debug" To Reduce Polling Loops #define TEMP 0x0 #define PREVB 0x0 #define PREVCVA 0x0 #define char_hi 0x0 #define CHAR_LO 0x0 #define BUFFER 0x0 ;************************************************************ ; reset and interrupt vectors org 0x000000 ; Reset Vector Address goto Start org 0x00008 ; Interrupt Vector Address nop goto ISR ;************************************************************ ; program code starts here org 0x000912 nop Debounce MACRO Port, Pin ; "Speed" is the PICmicro's Clock Speed variable DlayCount DlayCount = .250000000 / .10000000 ; Calculate the number of Cycles in 20 msecs DlayCount = .156250 / DlayCount DlayCount = 0x010000 - DlayCount ; on the PICmicro MCU clock speed ; Going high nop btfsc Port, Pin ; Wait for Button Released goto $ - 2 movlw LOW DlayCount ; Initialize Dlay for a 20 msec movwf Dlay ; Delay movlw HIGH DlayCount movwf Dlay + 1 bcf STATUS, Z ; Make Sure that Zero is Reset incfsz Dlay, f goto $ + 2 incf Dlay + 1, f btfsc Port, Pin ; Button Still Released? goto $-12 ; No - Loop Around Again btfss STATUS, Z ; Zero Flag Set (20 mSecs Past?) goto $-12 nop Endm ; End the Macro Start clrf PORTA movlw 0xFF movwf TRISA clrf PORTB ; clear all bits of PORTB movlw 0xFF ;Port B are inputs movwf TRISB ; Set PORTB as inputs clrf PORTD ;clear and set port d as inputs movwf TRISD clrf PORTE movlw b'00000111' movf TRISE call InitializeAD ; configure A/D module call InitSer bcf INTCON,TMR0IF ; clear the overflow bit bsf INTCON,GIE ; enable global interrupt bsf INTCON,TMR0IE ; enable timer0 interrupts Timer0 movlw b'11000111' ;on, 8-bit, 1:256 prescale -- about 26 ms till overflow movwf T0CON bsf T0CON,TMR0ON ; enable the timer ; call InitSCP Main btfss PORTB,6 goto Main goto SCP nop SCP call InitSCP ; Get AD0 value Adc0 bcf ADCON0,CHS0 bcf ADCON0,CHS1 bcf ADCON0,CHS2 bcf ADCON0,CHS2 bsf ADCON0,ADON call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert Send0 movlw A'0' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Thou, w movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc1 bsf ADCON0,CHS0 ;switch to AN1 (001) bsf ADCON0,ADON call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert Send1 movlw A'1' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Thou, w movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc2 bcf ADCON0,CHS0 ;switch to AN2 (010) bsf ADCON0,CHS1 bsf ADCON0,ADON call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert Send2 movlw A'2' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Thou, w movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc3 movlw b'00001101' movwf ADCON0 call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert Send3 movlw A'3' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Thou, w movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc4 bcf ADCON0,CHS0 ;switch to AN4 (100) bcf ADCON0,CHS1 ; bsf ADCON0,CHS2 ; bsf ADCON0,ADON call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert Send4 movlw A'4' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Thou, w movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc5 movlw b'00010101' movwf ADCON0 call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert Send5 movlw A'5' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Thou, w movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc6 movlw b'00011001' movwf ADCON0 bcf ADCON2,7 ;Left justify the result so we can drop 2 LSBs call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert256 Send6 movlw A'6' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Hund, w movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll movlw A'1' movwf TXREG call TxPoll movlw A'5' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movlw A'2' movwf TXREG call TxPoll movlw A'1' movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc7 movlw b'00011101' movwf ADCON0 call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert32 Send7 movlw A'B' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc8 movlw b'00100001' movwf ADCON0 call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert32 Send8 movlw A'C' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll movlw A'D' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Adc9 movlw b'00100101' movwf ADCON0 call SetupDelay bsf ADCON0,GO ; Start first A/D conversion call Test call Convert32 Send9 movlw A'E' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll movlw A'F' movwf TXREG call TxPoll movlw A'J' movwf TXREG call TxPoll movf Tens, w movwf TXREG call TxPoll movf Ones, w movwf TXREG call TxPoll movlw 0X4E movwf TXREG call TxPoll Goback ;set everything back and loop in synth mode bsf ADCON2,7 ;Right justify the result again goto SCP ;=============================================================== Test btfsc ADCON0,GO ;poll adc - is it done? goto Test ;no ; bcf PIR1,ADIF ;yes return Convert clrf Thous clrf Hund clrf Tens clrf Ones clrf Tens_Ones movf ADRESL,W movwf NumL movf ADRESH,W movwf NumH call Thous call bin2dec999fast movf Tens_Ones,W call BinToASCII movwf CHAR_LO movlw 0x30 addwf Hund return Convert256 clrf Hund clrf Tens clrf Ones clrf Tens_Ones movf ADRESH,W movwf NumL clrf NumH call bin2dec999fast movf Tens_Ones,W call BinToASCII movwf CHAR_LO movlw 0x30 addwf Hund return Convert32 clrf Hund clrf Tens clrf Ones clrf Tens_Ones movf ADRESH,W movwf NumL rrcf NumL bcf STATUS,C rrcf NumL bcf STATUS,C rrcf NumL bcf STATUS,C movlw .6 sublw NumL ;offset the volume a bit bcf STATUS,Z ; just in case clrf NumH call bin2dec999fast movf Tens_Ones,W call BinToASCII movwf CHAR_LO return ;************************************************************ ; InitializeAD - initializes and sets up the A/D hardware. ; Select AN0 to AN3 as analog inputs, RC clock, and read AN0. InitializeAD ; bsf ADCON0,0 ; ADC on! clrf ADCON0 movlw b'00000101' clrf ADCON1 ; Port A pins are all ADC and voltage references are VSS VDD AN10,AN11,AN12 are DIGITAL movlw B'10101101' ; Select RC osc, 101 = 12 TAD 101 = Fosc/16 movwf ADCON2 ; right justified result bcf PIR1,ADIF bcf PIE1,ADIE return ;************************************************************ ;Initialize the TX RX serial InitSer ; initialize the serial! movlw b'01001000' movwf BAUDCON movlw .129 ;.129 16 bit high mode movwf SPBRG clrf SPBRGH bsf TXSTA,BRGH ; high baud clrf PORTC movlw b'10111111' movf TRISC ; bcf TRISC,6 ; clear RC6 ; bsf TRISC,7 ; set RC7 bcf TXSTA,SYNC ; transmit bit bsf RCSTA,SPEN ; enable receive bsf TXSTA,TXEN ; transmit bit ;bsf RCSTA,CREN ; enable continuous reception Return InitSCP ;call TxPoll movlw 5Ch movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw 'R' movwf TXREG call TxPoll ; movlw '0' ; movwf TXREG ; call TxPoll ; movlw 'N' ; movwf TXREG ; call TxPoll return TxPoll btfss TXSTA,TRMT ;poll trmt - has it sent? goto TxPoll ;no nop ;yes return ;************************************************************ ; This is used to allow the A/D time to sample the input ; (acquisition time). SetupDelay movlw .30 ; Delay time movwf TEMP SD decfsz TEMP, F ; Delay loop goto SD return Delay ;17499991 cycles movlw 0xff movwf D1 movlw 0x10 movwf D2 movlw 0x00 movwf D3 Delay_0 decfsz D1, f goto $-2 decfsz D2, f goto $-2 decfsz D3, f goto Delay_0 ;4 cycles (including call) return bin2dec999fast ; convert ; add b[3:0] + b[7:4] for ones swapf NumL, w ;Add the upper and lower nibbles addwf NumL, w ;to get the one's digit andlw 0x0F ; if sum is bigger than 15 (DC is set), add 16 to BCD result btfsc STATUS,1 ;Go through a binary to bcd addlw 0x16 ;conversion for just the one's ; if lower digit overflowed again, add 16 again btfsc STATUS,1 ;digit addlw 0x06 ; make sure the lower digit is in 0..9 range. If not, do BCD ; correction (add 6) addlw 0x06 btfss STATUS,1 addlw -0x06 ; add now 5*b[4] to ones accumulator and b[4] to tens, doing the ; BCD correction at the same time btfsc NumL, 4 ;bit 4 is a special case addlw 0x16 - 1 + 0x6 BTFSS STATUS,1 addlw -0x06 ; here we have converted already bits 0 to 4: ; ones = b[3:0] + b[7:4] + b[9:8] + 5*b[4] + 5*b[8] ; --------------- ------- ; tens = 2*b[6:5] + b[4] + b[6:5] + 2*b[7] + 5*b[8] + b[9] ; ---- ; hund = b[9:7] + b[9] ; now just test bits 5 to 7 and add their decimal weights to ; tens only (bit 7 also affects hundreds). We can add maximum ; 11 to tens digit here, so it will be less than 16 and not overflow. ;now adjust the ten's digit btfsc NumL, 5 ;2^5 = 32, so add 3 to the ten's addlw 0x30 ;digit if bit 5 is set btfsc NumL, 6 ;2^6 = 64, so add 6 addlw 0x60 ;if bit 6 is set btfsc NumL, 7 ;2^7 = 128, so add 2 (the ten's addlw 0x20 ;digit) if bit 7 is set ; do decimal correction for tens and propagate carry to hundreds addlw 0x60 ;convert the ten's digit to bcd clrf Hund rlcf Hund, f ;if there's a carry, then the input btfss Hund, 0 ;was greater than 99. addlw -0x60 movwf Tens_Ones ; Here we are done with bits 5 to 7 (except bit 7 for hundreds): ; ones = b[3:0] + b[7:4] + b[9:8] + 5*b[4] + 5*b[8] ; --------------- ------- ; tens = 2*b[6:5] + b[4] + b[6:5] + 2*b[7] + 5*b[8] + b[9] ; -------- ---- ------ ------ ; hund = b[9:7] + b[9] ; test bit 8, and add what it contributes to ones and tens movlw 0x66 ;2^8 = 256, so add 0x56 to Tens_Ones btfsc NumH, 0 movlw 0x56 + 0x66 ;add 0x66 for decimal adjust addwf Tens_Ones, f ; do decimal correction movff STATUS,TempStatus ; Save status so incf doesn't mess up C and DC BTFSC STATUS,C incf Hund, f movff TempStatus,STATUS ; Restore the status movlw 0h BTFSS STATUS,0 iorlw 0x60 BTFSS STATUS,1 iorlw 0x06 subwf Tens_Ones, f ; Here we are done with bit 8: ; ones = b[3:0] + b[7:4] + 2*b[9] + b[8] + 5*b[4] + 5*b[8] ; --------------- ----- ------- ------ ; tens = 2*b[6:5] + b[4] + b[6:5] + 2*b[7] + 5*b[8] + b[9] ; -------- ---- ------ ------ ------ ; hund = b[9:7] + b[9] ; test bit 9 (it adds 2 to ones, 1 to tens, and 5 to hundreds), ; but ignore hundreds yet movlw 0x66 ;2^9 = 512, so add 0x12 to Tens_Ones btfsc NumH, 1 movlw 0x12 + 0x66 addwf Tens_Ones, f movff STATUS, TempStatus ; Save so incf doesn't mess up C and DC BTFSC STATUS,C incf Hund, f movff TempStatus,STATUS ; Restore saved status movlw 0h BTFSS STATUS,0 iorlw 0x60 BTFSS STATUS,1 iorlw 0x06 subwf Tens_Ones, f ; Now we have a ready result for ones and tens: ; ones = b[3:0] + b[7:4] + 2*b[9] + b[8] + 5*b[4] + 5*b[8] ; --------------- ------ ----- ------- ------ ; tens = 2*b[6:5] + b[4] + b[6:5] + 2*b[7] + 5*b[8] + b[9] ; -------- ---- ------ ------ ------ ----- ; hund = b[9:7] + b[9] ; now just test bits 7, 8, and 9 and add their share to hundreds ; (without any BCD correction, because we assume input value is ; between 0 and 999, so hundreds can't be more than 9) ; btfsc NumL, 7 ;finish with hundreds ; incf Hund, f ; movlw 2 ; btfsc NumH, 0 ; addwf Hund, f ; movlw 5 ; btfsc NumH, 1 ; addwf Hund, f ;That's it! ;Wait, let's optimize the last few lines... ; hund = b[9:7] + b[9] rlcf NumL, w ; copy bit 7 to carry rlcf NumH, w ; load w with bits 9 to 7 btfsc NumH, 1 ; add b[9] addlw 1 ; addwf Hund, f ; add it to hundreds movlw .10 cpfslt Hund ;If Hund is greater than 10 make it 9 to limit numbers to 999 call Cutoff return Thous clrf Thou btfsc NumH,3 ;Number is greater than 2047! goto two ;Thou is now 2 btfsc NumH,2 goto one btfss NumH,1 return btfss NumH,0 return ;Number is greater than 767 and thus worth our time movlw 0xE7 cpfslt NumL ;if NumH:NumL is > 999 then goto one ;thou is 1 zero movlw '0' movwf Thou return one movlw 0x07 cpfslt NumH goto mtwo ;could be >2000 movlw '1' movwf Thou bcf NumH,2 ; condition it for the binary to BCD calc return two movlw '2' movwf Thou bcf NumH,3 bcf NumH,2 ; condition it for the binary to BCD calc return mtwo movlw 0xE7 cpfslt NumL ;if greater than 7:CF (1,999) goto two goto two movlw '1' movwf Thou bcf NumH,2 ; condition it for the binary to BCD calc return Cutoff movlw .0 movwf Hund return BinToASCII movwf char_hi ; save byte temporarily swapf char_hi,W andlw 0x0F ; mask out top nibble, preserv low nibble addlw 0x30 ; then finally add 58 to get 'proper' ascii movwf Tens movf char_hi,W andlw 0x0F ; mask out top nibble, preserv low nibble addlw 0x30 ; then finally add 58 to get 'proper' ascii movwf Ones return Inchi incf NumH clrf NumL bcf STATUS, Z return Talk ;Get it to say 20, 96, 21, 114, 22, 88, 23, 5, 183, 7, 159, 146, 164, 147, 151, 145, 176 in decimal movlw .20 movwf TXREG call TxPoll movlw .96 movwf TXREG call TxPoll movlw .21 movwf TXREG call TxPoll movlw .114 movwf TXREG call TxPoll movlw .22 movwf TXREG call TxPoll movlw .88 movwf TXREG call TxPoll movlw .23 movwf TXREG call TxPoll movlw .5 movwf TXREG call TxPoll movlw .183 movwf TXREG call TxPoll movlw .7 movwf TXREG call TxPoll movlw .159 movwf TXREG call TxPoll movlw .146 movwf TXREG call TxPoll movlw .164 movwf TXREG call TxPoll movlw .147 movwf TXREG call TxPoll movlw .151 movwf TXREG call TxPoll movlw .145 movwf TXREG call TxPoll movlw .176 movwf TXREG call TxPoll DelayBig call Delay call Delay call Delay return ;==================================================================== ISR ; Interrupt service routine! btfss INTCON,TMR0IF ;did timer0 overflow? retfie ;no? go home! bcf INTCON,TMR0IF ; clear it Check_buttons ;Check the momentary buttons on port B movlw 0x00 cpfseq PORTB ; Compare portB with 0 call Button_scan call Button_scan_d exit retfie ; if equal to zero Button_scan btfsc PORTB, 5 goto Softreset ; btfsc PORTB, 6 ; obsolete ; btg MODE, 6 ; btfsc PORTD, 5 ; call Tweak btfsc PORTB, 7 call Debounce5 Button_scan_d btfsc PORTD, 4 ;if 0 then skip call Debounce1 btfsc PORTD, 5 call Debounce2 btfsc PORTD, 6 call Debounce3 btfsc PORTD, 7 call Debounce4 retfie Debounce1 Debounce PORTD,4 call Square return Debounce2 Debounce PORTD,5 call Triangle return Debounce3 Debounce PORTD,6 call Sine return Debounce4 Debounce PORTD,7 call Saw return Debounce5 Debounce PORTB,7 call None Return Square movlw 'R' movwf TXREG call TxPoll movlw '8' ;Send ASCII 255 to speakjet for square wave on. movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '1' movwf TXREG call TxPoll movlw '9' movwf TXREG call TxPoll movlw '5' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll return Triangle movlw 'R' movwf TXREG call TxPoll movlw '8' ;Send ASCII 254 to speakjet for triangle wave on. movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '1' movwf TXREG call TxPoll movlw '9' movwf TXREG call TxPoll movlw '4' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll return Sine movlw 'R' movwf TXREG call TxPoll movlw '8' ;Send ASCII 253 to speakjet for sine wave on. movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '1' movwf TXREG call TxPoll movlw '9' movwf TXREG call TxPoll movlw '3' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll return Saw movlw 'R' movwf TXREG call TxPoll movlw '8' ;Send ASCII 252 to speakjet for saw wave on. movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '1' movwf TXREG call TxPoll movlw '9' movwf TXREG call TxPoll movlw '2' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll return None movlw 'R' movwf TXREG call TxPoll movlw '8' ;Send ASCII 0 to speakjet for no modulation movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll return Softreset movlw '\' movwf TXREG call TxPoll movlw 'A' ;Send ASCII to reset via software. movwf TXREG call TxPoll goto Main Tweak ;squeal a little movlw 'R' movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '2' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll movlw '1' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '1' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll movlw '4' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '3' movwf TXREG call TxPoll movlw '5' movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll movlw '2' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw '0' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll movlw 'B' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll movlw 'C' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll movlw 'E' movwf TXREG call TxPoll movlw 'J' movwf TXREG call TxPoll movlw '7' movwf TXREG call TxPoll movlw 'N' movwf TXREG call TxPoll return end