PDA

View Full Version : DCD command - need some advice



malc-c
- 16th December 2006, 12:24
From a previous thread Steve suggested a simple test program that I would like to embellish on to send a pattern sequence to port B of a 16F873a. The code I've come up with is shown below, but I keep getting the "Bad expression" error when I try to use a varible in the DCD line.

If I enter PORTB=DCD patt3 the code compiles file, However I want to change the pattern depending on the value of a varible (either swcount or N) and I've tried

PORTB=DCD patt,N
PORTB=DCD patt,(N)
PORTB=DCD patt(N)
And replacing N with swcount and it still errors.

Can the DCD command be used in such a way ?



;************* set up pattern data **********

Patt1 DATA 16,1,2,4,8,16,32,64,128,128,64,32,16,8,4,2,1
Patt2 DATA 8,129,66,36,24,24,36,66,129
Patt3 DATA 16,1,3,2,6,4,12,8,24,16,48,32,96,64,192,128,0
Patt4 DATA 16,1,128,2,64,4,32,8,16,8,32,4,64,2,128,1,0
Patt5 DATA 12,24,60,126,255,231,195,129,0,129,195,231,255
Patt6 DATA 13,1,2,4,8,17,34,68,136,16,32,64,128,0
Patt7 DATA 8,128,64,32,16,8,4,2,1

;************* set up PIC ********************

ADCON1=$0F
CMCON = 7 ' Digital inputs
CCP1CON = 0 ' PWM off
TRISA=%11100111 'set PORTA as all input apart from A3 & A4
TRISB=%00000000 'set PORTB as all output
PORTB=0

;************* set up variables ***************

ByteA var byte
D var byte
scale var byte ;used in the POT command
Scale = 254
steps var byte
swcount var byte
swcount=3 ; set to 3 for testing only
N var byte

;**************** main program ********************
main:
if swcount = 1 then read Patt1, steps ;read the first value in data string patt1 and place it in steps
if swcount = 2 then read Patt2, steps
If swcount = 3 then read Patt3, steps
if swcount = 4 then read Patt4, steps
if swcount = 5 then read Patt5, steps
If swcount = 6 then read Patt6, steps
If swcount = 7 then Read patt7, steps

n = swcount

Pot PORTA.1,scale,D ;used to read value from 10k pot
for bytea=0 to steps
PORTB=DCD patt,n
PAUSE D
NEXT
goto main


The other question I have, is on a 16F628A the datasheet shows the program memory (flash words) as 2048, data memory as 224 bytes SRAM and 128 EEPROM bytes. However the Datasheet for the 16F873A shows Program memory as 7.2K bytes / 4096 single word instructions. Can someone advise why / what is meant by the two entries for the '873A's program memory, and if it's different to the '628A's memory ?

mister_e
- 16th December 2006, 13:41
i'm not sure what you expect at the output, but when you said PORTB=DCD patt3 worked but you want to use some kind of text substitution, and use something like PORTB=DCD patt[x] and if x=3 work... you'll like the following


;************* set up pattern data **********

Patt1 DATA 16,1,2,4,8,16,32,64,128,128,64,32,16,8,4,2,1
Patt2 DATA 8,129,66,36,24,24,36,66,129
Patt3 DATA 16,1,3,2,6,4,12,8,24,16,48,32,96,64,192,128,0
Patt4 DATA 16,1,128,2,64,4,32,8,16,8,32,4,64,2,128,1,0
Patt5 DATA 12,24,60,126,255,231,195,129,0,129,195,231,255
Patt6 DATA 13,1,2,4,8,17,34,68,136,16,32,64,128,0
Patt7 DATA 8,128,64,32,16,8,4,2,1

;************* set up PIC ********************

ADCON1=$0F
CMCON = 7 ' Digital inputs
CCP1CON = 0 ' PWM off
TRISA=%11100111 'set PORTA as all input apart from A3 & A4
TRISB=%00000000 'set PORTB as all output
PORTB=0

;************* set up variables ***************

Patt var byte [8]
asm
MOVE?CB _Patt1,_Patt+1 ; Patt[1]
MOVE?CB _Patt2,_Patt+2 ; Patt[2]
MOVE?CB _Patt3,_Patt+3 ; Patt[3]
MOVE?CB _Patt4,_Patt+4 ; Patt[4]
MOVE?CB _Patt5,_Patt+5 ; Patt[5]
MOVE?CB _Patt6,_Patt+6 ; Patt[6]
MOVE?CB _Patt7,_Patt+7 ; Patt[7]
endasm


ByteB var byte
ByteA var byte
D var byte
scale var byte ;used in the POT command
Scale = 254
steps var byte
swcount var byte
swcount=3 ; set to 3 for testing only
N var byte

;**************** main program ********************
main:
if swcount = 1 then read Patt1, steps ;read the first value in data string patt1 and place it in steps
if swcount = 2 then read Patt2, steps
If swcount = 3 then read Patt3, steps
if swcount = 4 then read Patt4, steps
if swcount = 5 then read Patt5, steps
If swcount = 6 then read Patt6, steps
If swcount = 7 then Read patt7, steps

n = swcount

Pot PORTA.1,scale,D ;used to read value from 10k pot
FOR ByteA=0 to steps
PORTB=DCD Patt[n]
PAUSE D
NEXT
PAUSE 500
GOTO main

As you see, i didn't touch too much your previous code.. just add some spices in.

Maybe Darrel or someone else have a better solution?

SteveB
- 16th December 2006, 14:04
The other question I have, is on a 16F628A the datasheet shows the program memory (flash words) as 2048, data memory as 224 bytes SRAM and 128 EEPROM bytes. However the Datasheet for the 16F873A shows Program memory as 7.2K bytes / 4096 single word instructions. Can someone advise why / what is meant by the two entries for the '873A's program memory, and if it's different to the '628A's memory ?


In the Mid-Range PICs (16Fxxxx), each instruction is 14 bits long, and is considered a "single word instruction." So, 2048 words in the 628A is half the instructions as 4096 words in the 873A. The 7.2K bytes is just (4096 words * 14 bits)/8 bits = total actual bytes. Not a very useful number (IMO) when using these devices.

HTH,
SteveB

malc-c
- 16th December 2006, 15:45
Thanks guys for your replies.

Steve,
When I said it worked, I mean it compiles without error, not that it actually produced the correct pattern sequence on the LEDs attached to PORT B. I based this on the example you provided in the post on my troubles with programming the 2550 chip. Your code below produced a nice chase sequence whe programmed into the 16F873A



ByteA var byte

main:
for bytea=0 to 7
PORTB=DCD BYTEA
PAUSE 250
NEXT
PORTB=255
PAUSE 250
goto main


If I read your code correctly DCD is converting the value of bytea (0 to 7) to binary and then displaying this vaule on port B. ie 1 = 00000001, 2 = 00000010 etc. I was hoping that I could read the pattern string, take the values of each step (0 to 255) and use DCD to display the pattern on port B. Hence


for bytea=0 to steps
PORTB=DCD patt3
PAUSE D
NEXT


Funny thing is that as I'm typing this I think I know where 'm going wrong. I need to read each value in the sequence. My old code (for the 16F628A) used


if swcount = 1 then READ (Patt1+counts), PORTB ;read the next value in patt1 and display it on PORTB
if swcount = 2 then READ (Patt2+counts), PORTB
if swcount = 3 then READ (Patt3+counts), PORTB
if swcount = 4 then READ (Patt4+counts), PORTB
if swcount = 5 then READ (Patt5+counts), PORTB
if swcount = 6 then READ (Patt6+counts), PORTB
if swcount = 7 then READ (Patt7+counts), PORTB


So I tried the following (hopefully you will see my logic ;)



n = swcount

Pot PORTA.1,scale,D ;used to read value from 10k pot
for bytea=0 to steps
READ (Pattn+bytea), PORTB
PAUSE D
NEXT
goto main

Thinking that it would READ pattern 3 (as I set SWCOUNT to 3 for testing) + the value for bytea (0, to STEPS) and then output it to PORT B. But I get an error "Bad Expression" with the READ (PatN+bytea), PORTB line.

SteveB (and Steve if you can help ;) )

Would the differences between the two chips that you stated cause the use of the DATA statement be handled differently between the two PICs. The reason I ask was then If I use the code I originally wrote for the 16F628a with the 16F873a, the patterns are not displayed in the same way on the '873a.

Thanks for your help

mister_e
- 16th December 2006, 16:17
how about this one?


;************* set up pattern data **********

Patt1 DATA 16,1,2,4,8,16,32,64,128,128,64,32,16,8,4,2,1
Patt2 DATA 8,129,66,36,24,24,36,66,129
Patt3 DATA 16,1,3,2,6,4,12,8,24,16,48,32,96,64,192,128,0
Patt4 DATA 16,1,128,2,64,4,32,8,16,8,32,4,64,2,128,1,0
Patt5 DATA 12,24,60,126,255,231,195,129,0,129,195,231,255
Patt6 DATA 13,1,2,4,8,17,34,68,136,16,32,64,128,0
Patt7 DATA 8,128,64,32,16,8,4,2,1

;************* set up PIC ********************

ADCON1=$0F
CMCON = 7 ' Digital inputs
CCP1CON = 0 ' PWM off
TRISA=%11100111 'set PORTA as all input apart from A3 & A4
TRISB=%00000000 'set PORTB as all output
PORTB=0

;************* set up variables ***************

Patt var byte [8]
asm
MOVE?CB _Patt1,_Patt+1 ; Patt[1]
MOVE?CB _Patt2,_Patt+2 ; Patt[2]
MOVE?CB _Patt3,_Patt+3 ; Patt[3]
MOVE?CB _Patt4,_Patt+4 ; Patt[4]
MOVE?CB _Patt5,_Patt+5 ; Patt[5]
MOVE?CB _Patt6,_Patt+6 ; Patt[6]
MOVE?CB _Patt7,_Patt+7 ; Patt[7]
endasm

ByteA var byte
D var byte
scale var byte ;used in the POT command
Scale = 254
steps var byte
swcount var byte
swcount=7 ; set to 3 for testing only
D=250
;**************** main program ********************
main:
for swcount=1 to 7
read patt[swcount],steps
for bytea=1 to steps
READ PATT[SWCOUNT]+BYTEA,PORTB
PAUSE D
NEXT
next
GOTO MAIN

noticed that i skiped the POT command but use a fixed 250mSec delay. It's working here. if you want to use DCD, you'll need to modify the DATA lines and use bit# instead of Decimal value. No big deal ;)

It shouldn't be different from one to another. DATA remain DATA. PORTB remain PORTB. Well i can't explain why if it doesn't create the expected results with the above suggestion :(

Too bad, MPASM text substitution doesn't seems to work with Bytes variable in the #V(Variable) area.. it would be too convenient...

EDIT: Note that MOVE?CB _Patt1,_Patt+1 can be replace by Patt[1]=Patt1 etc...

The whole MOVE?CB block (or Patt[x]=Pattx) could also be replace using MPASM text substitution like this


asm
local a=1
while a<7
MOVE?CB _Patt#v(a),_Patt+a
a+=1
endw
endasm

malc-c
- 16th December 2006, 18:33
how about this one?

Yup - works a treat here too... the LEDs are cycling through all the pattern sequences quite nicely :)

Now sorry to be a pain in the a$$, but you lost me right at the point you went asm
MOVE?CB _Patt1,_Patt+1 ; Patt[1]
:) :)

I assume that this could be done in PBP without dropping out to assembly code, hence the Note that MOVE?CB _Patt1,_Patt+1 can be replace by Patt[1]=Patt1 etc... statement ????

Sorry if this seems dumb questions, but now that 'm moving away from the simple basic commands and the fact I was (and still am) a bit rusty with my coding, all help to expand the learning curve with PBP is greatly apreciated

mister_e
- 16th December 2006, 18:44
So, i think i lost you pretty much more with the second asm code using the text substitution?

Sorry sometimes i'm getting sick with those MOVE?CB, PAUSE?C, macro and whatever else... It's the Darrel's fault!

Yup indeed the whole MOVE?CB ... block could be replace by using...


Patt[1]=Patt1
Patt[2]=Patt2
Patt[3]=Patt3
Patt[4]=Patt4
Patt[5]=Patt5
Patt[6]=Patt6
Patt[7]=Patt7


Now compile those line and open the .asm file... you'll discover somewhere those lines...


; C:\PBP_PROG\A.BAS 00040 Patt[1]=Patt1
MOVE?CB _Patt1, _Patt + 00001h

; C:\PBP_PROG\A.BAS 00041 Patt[2]=Patt2
MOVE?CB _Patt2, _Patt + 00002h

; C:\PBP_PROG\A.BAS 00042 Patt[3]=Patt3
MOVE?CB _Patt3, _Patt + 00003h

; C:\PBP_PROG\A.BAS 00043 Patt[4]=Patt4
MOVE?CB _Patt4, _Patt + 00004h

; C:\PBP_PROG\A.BAS 00044 Patt[5]=Patt5
MOVE?CB _Patt5, _Patt + 00005h

; C:\PBP_PROG\A.BAS 00045 Patt[6]=Patt6
MOVE?CB _Patt6, _Patt + 00006h

; C:\PBP_PROG\A.BAS 00046 Patt[7]=Patt7
MOVE?CB _Patt7, _Patt + 00007h

Interesting eh?

NOW, why i use the MOVE?CB first? Well didn't thought Patt[1]=Patt1 would worked... later i decide to try and... Woohhooo :D

So this is why i edited my previous post. I'm still learning as well. I guess we never stop anyways!

MOVE?CB: Is a PBP macro wich copy a Constant value to a Byte variable. Not much.

Glad to hear it's working as expected
Have fun!

malc-c
- 16th December 2006, 19:11
Thanks for the explanation...

SteveB
- 16th December 2006, 19:37
<img src="http://www.picbasic.co.uk/forum/attachment.php?attachmentid=1273&stc=1&d=1166301519">
Bravo Steve!

Nice explaination.


SteveB

mister_e
- 16th December 2006, 19:48
http://www.cbc.ca/arts/images/pics/charity2.jpg

Gracias, Merci, thank you,falemnderit, σασ ευχαριστώ, danke, grazie, ขอบคุณ, teşekkür ederim ,...,..
:D

malc-c
- 16th December 2006, 20:59
You guys crack me up !

Ok' I'm working my way through this version using the 16F873A, but I've hit a small issue which is so basic I can't see why it responds the way it does (it worked with the 16F628a).

I have set port A to all inputs and added


SW1 var PORTA.2 ;pattern selection switch


I have a 10k pull up resistor between pin 4 (RA2) and +5v with a tactile switch between pin 4 and GND.

I've added the code


if SW1=0 then swcount=swcount+1 ;check to see if up button pressed, if so add 1 to swcount
pause 60 ;debounce delay
If swcount>7 then swcount=1 ;error trap for exceeding max patterns


So in therory if the switch (sw1) is low then swcount is increased by 1, until it is > than 7 and if so then its swcount is reset to 1. This way the pattern is selected by pressing the switch.

However in practice, the PIC simply ignores any input on RA2, but more confusingly, it runs each pattern once in sequence, ie it cycles through the patterns as if the button is being pressed, so swcount must in some way be changing as the remainder of the code works if the above lines are remed out and swcount is manual set to 1, 2, 3 etc, which results in just the selected pattern running.



Pot PORTA.1,scale,D ;used to read value from 10k pot and set the speed
read patt[swcount],steps ;read the first value of the selected patter and place it in the variable steps
for C = 1 to steps ;for / next loop
READ PATT[SWCOUNT]+ C,PORTB ;reads the step value for selected pattern and send it to PORTB
PAUSE D ;delay for speed
NEXT
GOTO MAIN


Its probably me having a blonde moment (no offence to any fair haired madiens out there ;) ) - but can anyone shed some light why this isn't working.

SteveB
- 16th December 2006, 22:21
Ok' I'm working my way through this version using the 16F873A, but I've hit a small issue...

I have set port A to all inputs...

the PIC simply ignores any input on RA2, but more confusingly, it runs each pattern once in sequence, ie it cycles through the patterns as if the button is being pressed, so swcount must in some way be changing...


Pot PORTA.1,scale,D ;used to read value from 10k pot and set the speed
read patt[swcount],steps ;read the first value of the selected patter and place it in the variable steps
for C = 1 to steps ;for / next loop
READ PATT[SWCOUNT]+ C,PORTB ;reads the step value for selected pattern and send it to PORTB
PAUSE D ;delay for speed
NEXT
GOTO MAIN



Exactly what value have you put into ADCON1 to "set port A to all inputs" yet still get the Pot command to work? It seems as though you still might have some of them set as Analog Inputs.

SteveB

malc-c
- 16th December 2006, 22:49
Steve,

Here is the complete code (less the data for light patterns)


;************* set up PIC ********************

ADCON1=$0F
CMCON = 7 ' Digital inputs
CCP1CON = 0 ' PWM off
TRISA=%11111111 'set PORTA as all input
TRISB=%00000000 'set PORTB as all output
PORTB=0
PORTA=0
SW1 var PORTA.1 ;pattern selection switch

;************* set up variables ***************

Patt var byte [8] ;used to store the sequences
Patt[1]=Patt1
Patt[2]=Patt2
Patt[3]=Patt3
Patt[4]=Patt4
Patt[5]=Patt5
Patt[6]=Patt6
Patt[7]=Patt7


C var byte ;used to advance through pattern
D var byte ;used for the speed the sequence runs at
scale var byte ;used in the POT command
Scale = 254
steps var byte ;used for storing the number of steps in a sequence
swcount var byte ;used to select the required sequence required
swcount=1 ;set for testing only or default sequence

;**************** main program ********************
main:

if sw1=0 then swcount=swcount+1 ;check to see if up button pressed, if so add 1 to SWcount
pause 60 ;debounce delay
If swcount>7 then swcount=1 ;error trap for exceeding max patterns

;Pot PORTA.1,scale,D ;used to read value from 10k pot and set the speed
read patt[swcount],steps ;read the first value of the selected patter and place it in the variable steps
for C = 1 to steps ;for / next loop
READ PATT[SWCOUNT]+ C,PORTB ;reads the step value for selected pattern and send it to PORTB
PAUSE 250 ;delay for speed
NEXT
GOTO MAIN


In this example I've removed the wire from the 10 pot and set SW to the same pin as I have the pot working fine - and it works. If I set SW to RA0, RA2, RA3 etc the LEDs run through each pattern from 1 - 7 in a loop.

As you stated, it must be something is the setting of port A for digital. However I will at some point want one pin to be det up to use the A to D conversion as I want to input the line signal from a CD player to get the LEDs to flash / run to music at some stage in the future, all other inputs.

Sorry if it seems so basic, but as the other Steve can vouch for.. I'm very rusty on the PBP coding !

SteveB
- 16th December 2006, 23:41
<img src="http://www.picbasic.co.uk/forum/attachment.php?attachmentid=1277&stc=1&d=1166321219">

Have a look at the chart above, which shows the lower nibble of ADCON1 (it's in the datasheet in section 11). ADCON1 = $0F sets PORTA.2 (pin4 ) as the Vref-. Try ADCON1=$07. This will make all PORTA pins digital.

This should allow the Pot on PORTA.1 (pin 3) and the switch on PORTA.2 (pin4 ).

I haven't looked real closely at the rest of the code yet, but this should help.

SteveB

EDIT: I should have read up on the POT command (never had a use for it), so I had to make a couple of changes.

mister_e
- 17th December 2006, 08:46
Yup it should fix the problem. THE ADCON1=$0F setting was good for the previous PIC18F2550... wich, i feel, will gather dust for awhile ;)

I never used POT command, i prefer to use a real A/D converter instead. ADCIN or the eternal write/read PIC register solution. For an audio trigger... i would use a analog comparator instead as they react way faster.

malc-c
- 17th December 2006, 10:58
Guys, thanks once again.

I'll try the changes a little later and see how I get on.

If I read that table correctly, by entering the value in the left column, AN0, AN1 etc are set accordingly. So for example 0000 would cause all the pins (AN0 - AN7) to be analogue. 011x would do the opposite and make them all digital ?

I take it the $0f etc is just the Hex value for those dec numbers 0000 - 1111 ?


was good for the previous PIC18F2550... which, i feel, will gather dust for awhile

LOL - yeah.. you're probably right !


For an audio trigger... i would use a analog comparator instead as they react way faster

Steve, when I'm ready for looking at using music for the sound to light / chaser component I'll be interested to hear your suggestions as i've never used these sort of functions on a PIC before.

Thanks again

malc-c
- 17th December 2006, 15:43
Steve(s)

That works fine (I had no reason to doubt it wouldn't)

Slightly off topic, but I would like to run some ideas by you.

I want to have three sections, chase, music and s2l. Chase is the section I've already written (with your help) that simply runs the selected pattern at what ever speed is set by the pot. Music is where I want to make the 8 LEDs act like a level meter, just like that on most tape decks or top end video recorders. S2L is a sound to light, where the music is split by filters for bass, mid and treble.

For the music section I was thinking that i could simply connect the line in (1v peak to peak) from the CD player direct to a pin on the PIC and use the A to D convertion - although Steve mentioned someing about a comparator.. would this work ?

As for the sound to light section (s2l) I was thinking of building something like the filter section shown on this site http://sound.westhost.com/project62a.htm but only using bass, lower midrange, upper midrange and treble, with two LEDs being driven from each filter (ie bass drives RB0 and RB1, lower mid RB2 and RB3, upper mid RB4 and RB5 with treble driving RB6 and RB7) -

Comments would be wellcome

mister_e
- 17th December 2006, 20:35
The PIC have only 2 comparator if my memory serves me well, you if you need 3 different trigger source working at the same time you will need to add some external stuff... not really interesting.

Here the ADC solution have it's own advantages. It will allow as many trigger source as you have ADCs. ALSO you can implement software threshold on EACH audio band (low, mid, high)

well configured and speed optimized (clock source, acquisition time), ADC are not so slow, and BTW, we don't talk about something really timing critical... it's visual effect on audio. nobody will see the difference in a few ten or hundreds uSec of latency ;)

So you build a modern version of the old-timer 'color organ' ?

malc-c
- 17th December 2006, 21:30
Thanks for the reply,

Yes, I've been playing with making a colour organ (or sound to light unit) for some time. I originally made a basic unit using a 16F877 with code written in JAL (sory for swearing on the PBP forum :) ) - I then discoverd PBP and ported the basics over to a 16F628a, but never got around to doing the music side, and was limited by the number of pins so i couldn'l use the LCD.

Now I'm determined to build the filters, get a decent bass beat peak circuit made, and include a normal sound to light based. This is really my first advancement from the simple "flash a LED" and combined with the factI've not coded for a while its a steep learning curve ;)

I'll swat up on the ADC section of the manual. I have used RA2 and RA3 for switches, but as these are AN2 and AN3 I will change them to RA4 and RA5 so that will leave RA0/AN0, RA2/AN2, and RA3/AN3 for use with the audio side.

No doubt I'll probably need a helping hand to debug the code, but I'll see how far I can get on my own first, hopefully without blowing up the PIC (or the CD player !)

mister_e
- 17th December 2006, 21:37
Yeah... be carefull :D and good luck.

See you... soon ;)

skimask
- 18th December 2006, 03:43
Thanks for the reply,

Yes, I've been playing with making a colour organ (or sound to light unit) for some time. I originally made a basic unit using a 16F877 with code written in JAL (sory for swearing on the PBP forum :) ) - I then discoverd PBP and ported the basics over to a 16F628a, but never got around to doing the music side, and was limited by the number of pins so i couldn'l use the LCD.

Now I'm determined to build the filters, get a decent bass beat peak circuit made, and include a normal sound to light based. This is really my first advancement from the simple "flash a LED" and combined with the factI've not coded for a while its a steep learning curve ;)

I'll swat up on the ADC section of the manual. I have used RA2 and RA3 for switches, but as these are AN2 and AN3 I will change them to RA4 and RA5 so that will leave RA0/AN0, RA2/AN2, and RA3/AN3 for use with the audio side.

No doubt I'll probably need a helping hand to debug the code, but I'll see how far I can get on my own first, hopefully without blowing up the PIC (or the CD player !)


I've got a decent FFT running on an 18F4620 that pulls data from 0hz - 20khz at about 15 times per second onto the lcd. Check the video file at

http://web.ndak.net/~jdgrotte/picalyzer/picalyzer.htm

It works pretty good except the input filter that I had on it sucked bad. I was trying to cut off everything above 20khz to keep out the artifacts (or is it anti-aliasing? I forget), it never quite worked right, I gave up. But the digital part works great.
JDG

EDIT:
I forgot to mention....TURN DOWN YOUR SPEAKERS! Or at least get the dog out of the room! :)