PDA

View Full Version : Data tables again !



malc-c
- 13th June 2006, 00:18
Hi,

In a previous thread I was advised to use an array to generate a pattern sequence to be displayed on portB of an 16f628a PIC (var i, D and pat1 previously defined)



pattern3:
pat1[0]=129
pat1[1]=66
pat1[2]=36
pat1[3]=24
pat1[4]=36
pat1[5]=66
pat1[6]=129
pat1[7]=0

For i =0 to 7
portb=pat1[i]
pause d
next i


However while this will work, I thought that a better idea would be to store the patterns in the PIC using the DATA statement, and I have generated the following patterns sequence (each number is a step in the sequence)



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


So in the above example, Patt2 would run the sequence from 8 to 129 over and over again until the selection switches are pressed.

However I have two problems.

1) - Being a newbie, I can't see how I can use the read statement to read back the sequence and send it to the port. I did think about using an array, so that each number in thye sequence is placed in the array like the following



pattern[0]=8
pattern[1]=129
etc


2) - As you can see each sequence is not the same length and thus defining the length of the array becomes complicated ?? I assume I could place a digit or some form of marker to signify the end of sequence, but then I would need to count the digits in the data "string" and then set the array length to equal the count, and I'm not sure how to do this, or if its the correct way. Advice please ;)

Bruce
- 13th June 2006, 04:37
Here's several options.

http://www.pbpgroup.com/modules/wfsection/article.php?articleid=10

http://www.microengineeringlabs.com/resources/samples/x1/pbp/strtblx.bas

http://www.picbasic.co.uk/forum/showthread.php?t=1999&highlight=embedded+strings

The first link to Darrel Taylors example is one of the best.

The 2nd link is to one from MeLabs.

The 3rd is an old thread on Embedded Strings in Code Space.
It's a bit more advanced than the first two, but shows a ton
of other options.

SteveB
- 13th June 2006, 04:37
Malcom,
Here is something you might be able to try. Add as the first data item in each pattern the number of items in the sequence (I counted quick, so there might be a mistake in the values I added)


patt1 data 17,16,1,2,4,8,16,32,64,128,128,64,32,16,8,4,2,1
patt2 data 9,8,129,66,36,24,24,36,66,129
patt3 data 17,16,1,3,2,6,4,12,8,24,16,48,32,96,64,192,128,0
patt4 data 17,16,1,128,2,64,4,32,8,16,8,32,4,64,2,128,1,0
patt5 data 13,12,24,60,126,255,231,195,129,0,129,195,231,255
patt6 data 14,13,1,2,4,8,17,34,68,136,16,32,64,128,0
patt7 data 9,8,128,64,32,16,8,4,2,1


Then use the something like the following to get the actual data:


steps VAR BYTE
counts VAR BYTE
temp VAR BYTE

READ Patt1, steps
FOR counts = 1 TO steps
READ (Patt1 + counts), temp
PORTB = temp
NEXT counts


This should allow you to sequence through each step for the various patterns, regardless of size. You could then loop back and start the FOR..NEXT loop again if required. Or, move on to some other code, or a different pattern. Also, inside the FOR..NEXT loop you could insert any code you needed. Test for various conditions, and even break out of the loop if needed to move on.

NOTE: I have not tested the actual code, as it is ment to be just quick example to get across my idea, So don't cut and paste it. Try to understand the CONCEPT presented.

Regards,
Steve

malc-c
- 13th June 2006, 09:39
Steve, thanks for the reply,

I agree its the concept that I couldn't get my head round, and your code will make a good grounding for some trials. It all seems so logical now, but last night after a long day my brain went blank :)

Bruce, thanks also for replying, and I'll study those links in depth a little later (have work to do now :( )

malc-c
- 13th June 2006, 13:29
Steve,

I took your concepte and I'm getting somewhere, but I've hit a problem which I can't figure out.

The manual provides the following information when using the DATA statement



{Label} DATA {@Location,}Constant{,Constant...}

If the optional Location value is omitted, the first DATA
statement starts storing at address 0 and subsequent statements store
at the following locations.


so I followed the format and used patt1, patt2 etc as the lable and ommitted the address, thus causing patt1 to sit at address 0 by default. The manual then gives an example of how to store three numbers in the EEPROM memory



Store 10, 20 and 30 starting at location 4
DATA @4,10,20,30


Ok as I've used the default address and ommited the location my data statement looks like:


patt1 DATA 17,16,1,2,4,8,16,32,64,128,128,64,32,16,8,4,2,1

which also includes the number of steps as the first digit as suggested

So far so good.... moving on to the READ statement the manual states



READ Address,Var

Read a byte from the on-chip EEPROM at the specified Address and
stores the result in Var.


Using your concept code the program fell over when it encountered the line "READ Patt1, steps" so logic suggested that its looking for a location rather than the lable patt1. so I changed the patt1 to read "READ 4, steps" and that compiled OK.

Now the part that is confusing me is how to read back all the values in the data statement. It would be nice if the manual used the same example in the READ statement that it featued in the DATA statenment showing how to get back the digits 10, 20, 30. If I used your concept of "READ patt1 + count" with the correct syntax it gives


READ (0+1), temp


However would this then read the first byte of the DATA statement at the next address, as it would be interpreted as READ 1, temp... READ 2,temp etc or is the next address (1) be the next byte in the same DATA statement. If so I would then need to know the exact address for the start of the second DATA statement, and the Third etc

Also do I need to use hexdecimal for address locations, or can I stick to decimal, so that the second DATA statement would thus start at address 18

I'm now totally confused ??

With regards to Bruce's post, a lot of that was in assemble, and at my current level of understanding with Pics and PBP I would much rather stick with PBP.. which is a steep enough learning curve as it is, without having to get my head round asm code !

paul borgmeier
- 13th June 2006, 16:06
Coincidently in your first post, the first number you have in each row appears to be the count of the following bytes of data. i.e., it looks like this data already has SteveB's suggestion built in? I will assume it does – if it does not, add it in like Steve suggested.

What PIC are you using? If you are using the 16F628, which has 128 bytes of EEPROM you could do something like this (although a tad wasteful).

;patt1
Data @0, 16,1,2,4,8,16,32,64,128,128,64,32,16,8,4,2,1
;patt2
Data @20, 8,129,66,36,24,24,36,66,129
;patt3
Data @40, 16,1,3,2,6,4,12,8,24,16,48,32,96,64,192,128,0
;patt4
Data @60, 16,1,128,2,64,4,32,8,16,8,32,4,64,2,128,1,0
etc.

;The data could be found and read as follows (for patt3 for example)

patt VAR BYTE ; pattern of interest
EEadr VAR BYTE ; EEPROM address
dataloop VAR BYTE ; number of data bytes (SteveB's suggestion)
pattern VAR BYTE[20]
i var byte ; temp counter

patt = 3; want to get pattern 3 from EEPROM for example

EEadr = 20*(patt-1) ; = 40, patt1 would be at 0, patt 4 would be at 60, etc.

Read EEadr, dataloop ; find out how many data bytes to follow
if dataloop > 19 then error ; can't have more than 19 or goes into next patt area
FOR x = 1 TO dataloop
EEadr = EEadr + 1
READ EEadr, pattern[x]
next x

Do something with numbers here

error:
END

Paul Borgmeier
Salt Lake City, Utah
USA

SteveB
- 13th June 2006, 16:20
Malcom

Using your concept code the program fell over when it encountered the line "READ Patt1, steps" so logic suggested that its looking for a location rather than the lable patt1. so I changed the patt1 to read "READ 4, steps" and that compiled OK.

Exactly what didn't work? I actually did cut and paste this exact code and compiled based on a 16F877A:

patt1 data 17,16,1,2,4,8,16,32,64,128,128,64,32,16,8,4,2,1
patt2 data 9,8,129,66,36,24,24,36,66,129
patt3 data 17,16,1,3,2,6,4,12,8,24,16,48,32,96,64,192,128,0
patt4 data 17,16,1,128,2,64,4,32,8,16,8,32,4,64,2,128,1,0
patt5 data 13,12,24,60,126,255,231,195,129,0,129,195,231,255
patt6 data 14,13,1,2,4,8,17,34,68,136,16,32,64,128,0
patt7 data 9,8,128,64,32,16,8,4,2,1

steps VAR BYTE
counts VAR BYTE
temp VAR BYTE

READ Patt1, steps
FOR counts = 1 TO steps
READ (Patt1 + counts), temp
PORTB = temp
NEXT counts
And it compiled just fine. I just haven't programmed it into a pic to see what happens.
-----------------------------------------------------------------------------------
Additionally, in reference to the following items:

{Label} DATA {@Location,}Constant{,Constant...}

If the optional Location value is omitted, the first DATA
statement starts storing at address 0 and subsequent statements store
at the following locations.

READ Address,Var

Read a byte from the on-chip EEPROM at the specified Address and
stores the result in Var.

When using the DATA command with a {label}, what is being done by PBP is the label becomes a constant with a vaule equal to the Address. So there should not be any reason that the read command does not recognized the label as a valid Address.

Possibly posting you actual code and which PIC your using could help us puzzle this out for you. Also, the exact error/warning message you get when it compiles will also help.


Steve

Bruce
- 13th June 2006, 18:24
SteveB's code is exactly what you're looking for. You can make it even
smaller/faster by reading each value in the list directly onto the port.

Run this to see how it works.


Patt1 data 8,1,2,4,8,16,32,64,128
Patt2 data 8,128,64,32,16,8,4,2,1

steps VAR BYTE
counts VAR BYTE
temp VAR BYTE
TRISB = 0

MAIN:
READ Patt1, steps ' get number of EEPROM entries
FOR counts = 1 TO steps
READ (Patt1+counts), PORTB
PAUSE 50
NEXT counts

' now cycle LED's back the other way
READ Patt2, steps ' get number of EEPROM entries
FOR counts = 1 TO steps
READ (Patt2+counts), PORTB
PAUSE 50
NEXT counts
GOTO MAIN

END
When you give each line a label you can just reference the label name to find
the starting point or base address of each pattern in EEPROM.

Patt1 starts at the first available location in EEPROM. Patt2 starts at the next
available location after the last byte in Patt1.

You don't need to know the physical address of each pattern because each
one has already been assigned a label. Each label is a pointer to the base
address of each separate pattern in EEPROM.

malc-c
- 13th June 2006, 22:24
Guys what can I say but Thanks Bigtime :)

I did type out a long post detailing what I had done and that the only reason Steves code failed was down to my human error ! I compiled it again and it worked fine. However the post didn't appear (probably human error again - as its been a long day and I'm knackered !). Anyway I've now moved on since that intended post... so maybe it was just as well I closed the browser before posting !!

Bruce, I took your example code and it worked a treat. I've therefore edited out all the "work in progress" and included the full data tables and have a nice tight bit of code which works... more or less !

Here's the code.



PORTA = 0 ' declare port level BEFORE port direction = safe power-on
CMCON = 7 ' PortA Digital inputs
CCP1CON = 0 ' PWM off
VRCON = 0 ' Voltage reference disabled
OPTION_REG.7 = 0

TRISA=%11100011 'set PORTA as all input apart from A2,A3 & A4
TRISB=%00000000 'set PORTB as all output

DATA @1,word 625,0,word 545,word 750 ' pre-setting EEPROM

@RC_OSC_NOCLKOUT
@WDT_ON
@PWRT_ON
@MCLR_OFF
@BOD_ON
@LVP_OFF
@CPD_OFF
@PROTECT_OFF

;set up pattern data

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

;set up varibles

i var byte ;used for for next loops
D var byte ;used to store the result of the pot on port A1
scale var byte ;used in the POT command
Scale = 254 ;used to set range
SW1 var PORTA.6 ;up switch
SW2 var PORTA.0 ;down switch
SWcount var byte ;used as a place holder for patterns
swcount=1 ;set place holder to default to pattern 1

steps VAR BYTE ;used to store the number of steps in the pattern sequence
counts VAR BYTE ;used in the FOR NEXT loop to run through the sequence

;main program

Main:
Pot PORTA.1,scale,D ;used to read value from 10k pot
if sw1=0 then swcount=swcount+1 ;check to see if up button pressed, if so add 1 to SWcount
if sw2=0 then swcount=swcount-1 ;check to see if down button pressed if so delete 1 to SWcount
pause 60 ;debounce delay
If swcount>4 then swcount=4 ;error trap for exceeding max patterns
If SWcount<1 then swcount=1 ;error trap for exceeding min patterns

TRISB = 0
READ Patt1, steps ;get number of EEPROM entries
FOR counts = 1 TO steps ;advance to through the entries
READ (Patt1+counts), PORTB ;read the next entry and send the result to PORTB
PAUSE D ;pause period set by varible D
NEXT counts ;advance through loop to next position
goto main: ;go back to the main program and run again

END


When this is compiled I was expecting the PIC to run through just the first pattern in the sequence (Patt1). But the instead it cycles in a loop through all 7 sequences and then lights all LEDS on portB for a short period (about the same as that set by D ) and then repeats over and over.

I also need to come up with a means of using SWcount to select the pattern sequence contained in the read statement (rather than repeating the READ statement for every pattern), however I'm not sure how to have a varible select a lable...

Other than that.. I want to thank you guys for showing me the way, and improving my understanding of PBP

malc-c
- 13th June 2006, 22:55
I also need to come up with a means of using SWcount to select the pattern sequence contained in the read statement (rather than repeating the READ statement for every pattern), however I'm not sure how to have a varible select a lable...


Well its amazing what a cup of coffee can do ;-)

I came up with the following which works. Ok it might not be the best way, or the neatest.. but it worked !!



;main program

Main:
Pot PORTA.1,scale,D ;used to read value from 10k pot
if sw1=0 then swcount=swcount+1 ;check to see if up button pressed, if so add 1 to SWcount
if sw2=0 then swcount=swcount-1 ;check to see if down button pressed if so delete 1 to SWcount
pause 60 ;debounce delay
If swcount>7 then swcount=7 ;error trap for exceeding max patterns
If SWcount<1 then swcount=1 ;error trap for exceeding min patterns

TRISB = 0
gosub sel1 ;go to subroutine to select pattern
FOR counts = 1 TO steps ;advance to through the entries
gosub sel2 ;go to subroutine to advance through sequence
PAUSE D ;pause period set by varible D
NEXT counts ;advance through loop to next position
goto main: ;go back to the main program and run again

Sel1:
if swcount = 1 then read Patt1, 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
return

Sel2:
if swcount = 1 then READ (Patt1+counts), 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
RETURN

END


The only strange thing that is happening now is that at the end of each pattern sequence I get strange additional flash on some LEDS at the end (or start its hard to tell). On most patterns this tends to be RA3 or RA4, but on one RA0, RA2 and RA3 all flash together (one pulse) at the end of the sequence ???

Maybe I should look at the data tables a bit more ?

EDIT:
Thats really strange.. for the pattern of RA0, RA2 and RA3 to light I think I'm right is saying that PORTB would have to have 13 sent to it. - I can't see 13 anywhere in the vales of the last two patterns which is where this problem is occuring

Thanks for all your help... Boy I love coding with PBP... things actually happen :)

malc-c
- 13th June 2006, 23:30
Either that second cup of coffee helped, or I need glasses !

I rechecked the data strings and the offending digit was the first one after each step value (ie the second byte) - How I missed it I don't know !


Now that phase 1 is complete, its time to move on to phase 2. Uploading the data sequences via RS232 comms..... time to read the manual :)

And before you ask what phase 3 might be... its Music triggering.... Time to go searching for a circuit that will provide either a beat pulse to trigger the stepping of the pattern, or some form of filter so I can produce a 4 channel sound to light with RA0 & RA1 triggered by the bass, RA2 and RA3, lower midrange, RA4 and RA5 upper midgrange and finally RA6 and RA7 treble :)