Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Noob attempt at a PIC synth

Status
Not open for further replies.

MusicTech

New Member
https://www.electro-tech-online.com/custompdfs/2008/09/41291C.pdf

Code:
;Author Jake Wood
;Project Square Wave Keyboard
;Date 9 11 08

LIST	p=16F884		
include "P16F884.inc"
osccon 000; Oscillates at 31 kHz

bsf STATUS, RP0; to bank 1
movlw b'11111111' ;sets 255 to W
movfw TRISA ;all RA set to input
movfw TRISB ;all RB set to input
movlw b'11111110' ;sets 255 to W
movfw TRISC ;RC0-6 set to input RC7 to out
bcf STATUS, RP0 ;back to bank 0

cblock 0x20
 timer
 
endc
    

buttons

movlw 0
movfw RC7 ;turn RC7 off

WaitForPress

btfss PORTA,b'00000001'; If RA0 is high, call tone <----- first btfss
movlw d'119' ;C
call tone}
If(RA1==1){
movlw d'112' ;C#
call tone}
If(RA2==1){
movlw d'106' ;D
call tone}
If(RA3==1){
movlw d'100'  ;D#
call tone}
If(RA4==1){
movlw d'94'   ;E
call tone}
If(RA5==1){
movlw d'89'   ;F
call tone}
If(RA6==1){
movlw d'84'   ;F#
call tone}
If(RA7==1){
movlw d'79'   ;G
call tone}
If(RB0==1){
movlw d'75'   ;G#
call tone}
If(RB1==1){
movlw d'70'   ;A
call tone}
If(RB2==1){
movlw d'67'   ;A#
call tone}
If(RB3==1){
movlw d'63'   ;B
call tone}
If(RB4==1){
movlw d'59'   ;C
call tone}
If(RB5==1){
movlw d'56'   ;C#
call tone}
If(RB6==1){
movlw d'53'   ;D
call tone}
If(RB7==1){
movlw d'50'   ;D#
call tone}
If(RC0==1){
movlw d'47'   ;E
call tone}
If(RC1==1){
movlw d'44'   ;F
call tone}
If(RC2==1){
movlw d'42'   ;F#
call tone}
If(RC3==1){
movlw d'40'   ;G
call tone}
If(RC4==1){
movlw d'37'   ;G#
call tone}
If(RC5==1){
movlw d'35'   ;A
call tone}
If(RC6==1){
movlw d'33'   ;A#
call tone}
}
tone:
while(*The Bit that got us here*== 1)
movlw 1
movfw TRISC7
*delay for time*
movlw 0
movfw TRISC7
*delay for time*
}

end
 
Last edited:
Data Sheet: https://www.electro-tech-online.com/custompdfs/2008/09/41291C-1.pdf

I am a mega beginner a PICing please help especially with my osccon that bottom bit, I think it's really botched. Also, how do I make a Timer, I believe it's T0CK1 count the number of oscillations for the bottom part to set delays to make square waves (I hope to use internal osc. and clock).
...

;THANKS A LOT GUYS!!!!!!!!!!!!

Hi MusicTech,
welcome to the forum.

I would highly recommend you visit Nigel's tutorials, and work through them:



You have assembler mixed with C; I'm guessing you coppied parts of programs in order to get what you have. I started making the changes you need to build the project in MPLab, but there is so much which needs to change, and I don't have time to write your program for you. I will offer help, where I can though. :)

I would say, for a first project, stick to something simple, such as flash an LED. When you can do that, and understand what your code is doing, then move onto your PIC synth.
 
I actually didn't copy, but I have looked at tutorials. I did think that was odd that I saw if and goto statements mixed in with PIC assembly. I thought that was ok, i probably misunderstood though. Thanks could you just tell me where you think my main troubled areas are, and just tell me the concept and I will fix the code? Thanks
 
I am slowly editting my source as I go through the tutorial, is it looking better? decimal places aren't allowed in PIC, are they?
 
I actually didn't copy, but I have looked at tutorials. I did think that was odd that I saw if and goto statements mixed in with PIC assembly. I thought that was ok, i probably misunderstood though. Thanks could you just tell me where you think my main troubled areas are, and just tell me the concept and I will fix the code? Thanks

OK, for starters, put your code between [ code ] and [ /code ] without the spaces, to keep the formatting. I had a hard time setting the config bits, so just commented them out. You will need to resolve that...
For now, I have to go, but will check back and see how you are making out.

Code:
;Author Jake Wood
;Project Square Wave Keyboard
;Date 9 11 08

	LIST  P=16F883 ; declare device
#include "C:\Program Files\Microchip\MPASM Suite\P16F883.INC"
; normally just put #include <P16F883.INC> I had to use the full path name ...
; this include file defines the registers and PORTs as well as the register bits
; if you open this file, near the bottom, the configuration bits are defined:
;_CONFIG1 _LVP_OFF & _BOR_OFF & _CPD_OFF & _MCLRE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
; you need to AT LEAST turn off low voltage programming and the watch dog 
; I've configured the Master Clear as master clear... this chip has two config words
; _CONFIG2
; above gives an error:
; Error[122]   C:\SRC\000 BEGIN AGAIN\CABCON\CCS_THERMCALIBRATOR\JAKE.ASM 10 : Illegal opcode (_LVP_OFF)
; 
;      osccon 000 ;Set oscillator to LFINTOSC, but I don't think this is right
; *What other syntax is required here?

	cblock 	0x20 	; start of general purpose registers. See Data Sheet P. 23
		time		; This is how you declare variables in assembly
	endc			; you can put as many as you like here, then close with

    org 0x00		; this is the reset vector
	goto start		; just to jump over the interrupt location which is at 0x04

start
    clrf	PORTA 			; *I would be surprised if this syntax were right
    clrf	PORTB
    clrf	PORTC
    bsf		STATUS, RP0		; to bank 1
    movlw	b'11111111' 	; sets 255 to W
    movfw	TRISA 			; all RA set to input
    movfw	TRISB 			; all RB set to input
    movlw	b'11111110' 	; sets 255 to W
    movfw	TRISC 			; RC0-6 set to input RC7 to out
    bcf		STATUS, RP0 	; back to bank 0

;int time

buttons         ; you don't need this colon here : buttons is a lable
;	movlw 0
;	movfw RC7 ;turn RC7 off
	bcf	PORTC, 7	; this is the simplest way, so for now...
;	While(1){
; there aren't while loops in assembler, so lets make a lable
loop
; then just befor end, we will go to loop

; you don't have if tests, so do it like
; I'm assuming your button connects the pin to +5V, it is more common to 
; just put a ~10k resistor from each pin to +5V (a pull up resistor0 then
; coonnect your switch between each pin and ground, and in that case, look for a 
; 0, rather than 1 as a swich closed. You will also need to study up on switch contact bounce
; and either take care of it in software ( a ~10 mSecond delay then test again)
; or handle the bounce in hardware ( a schmidt trigger would do)
	btfsc	PORTA, 0 ; test to see if A0 is pressed, if it is, then do the next instruction
	call	Play_tone_1
	btfsc	PORTA, 1
	call	Play_tone_2
;		If(RA0==1){ ;waits for button to be pressed, goto appropriate tone
;	time=
;	goto tone}
;	If(RA1==1){
;	time=
;	goto tone}
;	If(RA2==1){
;	time=
;	goto tone}
;	If(RA3==1){
;	time=
;	goto tone}
;	If(RA4==1){
;	time=
;	goto tone}
;	If(RA5==1){
;	time=
;	goto tone}
;	If(RA6==1){
;	time=
;	goto tone}
;	If(RA7==1){
;	time=
;	goto tone}
;	If(RB0==1){
;	time=
;	goto tone}
;	If(RB1==1){
;	time=
;	goto tone}
;	If(RB2==1){
;	time=
;	goto tone}
;	If(RB3==1){
;	time=
;	goto tone}
;	If(RB4==1){
;	time=
;	goto tone}
;	If(RB5==1){
;	time=
;	goto tone}
;	If(RB6==1){
;	time=
;	goto tone}
;	If(RB7==1){
;	time=
;	goto tone}
;	If(RC0==1){
;	time=
;	goto tone}
;	If(RC1==1){
;	time=
;	goto tone}
;	If(RC2==1){
;	time=
;	goto tone}
;	If(RC3==1){
;	time=
;	goto tone}
;	If(RC4==1){
;	time=
;	goto tone}
;	If(RC5==1){
;	time=
;	goto tone}
;	If(RC6==1){
;	time=
;	goto tone}
;	}
tone
;	while(*The Bit that got us here*== 1)
;	movlw 1
;	movfw TRISC7
	;delay for time*
;	movlw 0
;	movfw TRISC7
;delay for time*
;}
	goto loop
Play_tone_1
;
;
Play_tone_2
;
;
end
 
I am slowly editting my source as I go through the tutorial, is it looking better? decimal places aren't allowed in PIC, are they?

I don't know, you didn't post it. But it sounds like you are making progress. I did a bit, but have to run. I'll check back later.
 
Hi MusicTech,

To test a bit in assembler we use the btfss (bit test file skip if set) or btfsc (...clear). We also use goto instead of while.

Something like,
Code:
Loop	btfsc	PORTA,0
	movlw	d'119'		;C
	btfsc	PORTA,1
	movlw	d'112'		;C#
	btfsc	PORTA,2
	movlw	d'106'		;D
	
	;add lots more

	btfsc	PORTC,6
	movlw	d'33'		;A#
	
	call	tone

	goto	Loop

OR,

Loop	btfss	PORTA,0
	goto	NotC
	movlw	d'119'		;C
	call	Tone
NotC	btfss	PORTA,1
	goto	NotCs
	movlw	d'112'		;C#
	call	Tone
NotCs	btfss	PORTA,2

	etc.

@BeeBop
There is a way to write
Code:
 and
without it being interpreted. Hit quote to see how.

Mike.
 
@BeeBop
There is a way to write
Code:
 and
without it being interpreted. Hit quote to see how.

Mike.

That's really cool!

Thanks Mike! :)

I expect the OP to be back soon. He went off to Nigel's tutorials for a read....

I believe if you can blink an LED, you can control the world. :p
 
But wouldn't saying

Code:
float int
be gouging into C?

Those numbers are all rounded. The delays have really long decimal values attached.

goto is C though. How can you use it in MPASM? Also, how does it know when subprocess is over. Like when you use call loop, how (By that I mean what syntax do you use) does it know where in the code to go back to where it was before?

btfss d,f is skip next command if d==f? So btfsc sets output low, right? how would you set it high?

For those who don't know, I just want to create a square wave synth. I am going to use different commands for wait for a certain input bit to go high, and then feed different highs and low at certain times, stored in w, through RC7.

By the way, I editted it some more. Please tell me if I used that first btfss right, before I go and change all of them
 
Last edited:
goto is C though. How can you use it in MPASM? Also, how does it know when subprocess is over. Like when you use call loop, how (By that I mean what syntax do you use) does it know where in the code to go back to where it was before?

Goto is originally from assembler. It was included in C just for completeness. It's use in C is now frowned upon. If you are calling a sub process (subroutine) then you use the call instruction, the pic remembers where it was and goes back to the same place when it executes a return instruction.
btfss d,f is skip next command if d==f? So btfsc sets output low, right? how would you set it high?
No, btfss only test the bit. To set a bit we use bsf, to clear a bit we use bcf. So to make A4 low (assuming it is set to output) we would do bcf PORTA,4.
By the way, I editted it some more. Please tell me if I used that first btfss right, before I go and change all of them
Not quite right. The btfss only skips over the next instruction and so it will skip the movlw but execute the call tone. If you look at the two examples I posted earlier, the second one is the one to use as this uses a goto to skip many instructions.

You may want to have a read of the sticky and some of the tutorials contained therein. There is also a very good online book here.

Mike.
 
But wouldn't saying

Code:
float int
be gouging into C?

Those numbers are all rounded. The delays have really long decimal values attached.

goto is C though. How can you use it in MPASM? Also, how does it know when subprocess is over. Like when you use call loop, how (By that I mean what syntax do you use) does it know where in the code to go back to where it was before?

btfss d,f is skip next command if d==f? So btfsc sets output low, right? how would you set it high?

For those who don't know, I just want to create a square wave synth. I am going to use different commands for wait for a certain input bit to go high, and then feed different highs and low at certain times, stored in w, through RC7.

By the way, I editted it some more. Please tell me if I used that first btfss right, before I go and change all of them

Hi, I'm not big on time, so will answer what I can...

Yes, I think there is a floating point lib in asm, I think on PIClist....

Yes, there is a goto and a call in Microchip assembler.



btfss d,f is skip next command if d==f? So btfsc sets output low, right? how would you set it high?

btfss PORTA,b'00000001'; If RA0 is high, call tone <----- first btfss
movlw d'119' ;C
call tone}

Bit_Test_in_File_Skip_if_Set - btfss tests the bit referred to (in your example tests bit f, in file d.) So if bit d, in file f is a logic 1, the next instruction will be skipped. If the bit is logic 0, the next instruction will execute. The reverse logic of this is btfsc = skip the next instruction if the bit is a logic 0.
It looks like you reversed the logic, so now a low on the pin signifies a button push?

It is ok, but instead of b'00000001' (which would be RA1, not 0) use:
Code:
    btfss       PORTA, 0        ;

Here is a snippet...

Code:
loop                                ; loop is a Label
    btfss       PORTA, 0        ;
    call         play_C            ;
    btfss       PORTA, 1        ;
    call         play_Csh


    goto       loop

play_C
      movlw   d'119'  ;
      movwf   time    ;
      call       delay   ;
      

play_Csh
        movlw d'112'  
        movwf time
        call  delay

But, I see Pommie has posted in the time since I started this, and I need to get going,,, I'm late..

so I would follow Pommie's advice, and I'll come back tomorrow when I have more time to help you.
 
Micro-controllers, and microprocessors, generally don't do floating point - it's all integer, and all a single byte/word in size. It's software which makes variables larger, or floating point.

The vast majority of cases don't require floating point anyway, and in this case certainly not - just scale as required. I'm not musical (and my daughter isn't here to ask), but there's a certain note type which is the shortest possible. Assign this a value of one, and make all other note types a multiple of that.

For simple monophonic tunes, you might have a look at:
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top