Separating a variable
TC
Posts: 1,019
Hello all,
Well the max7219 project is coming along, but I need to find a way to take a variable and split it into its individual digits. I know how to do it on the BS2, but I have never even tried it with the prop. Here is what I mean:
Counter = 12345
digit0 = 1
digit1 = 2
digit2 = 3
digit3 = 4
digit4 = 5
Here is the kicker, I don't want someone just to post a code and say here you go. How can I learn from that? I just want to know where should I look to figure it out. And any advice that would help.
Thanks
TC
Well the max7219 project is coming along, but I need to find a way to take a variable and split it into its individual digits. I know how to do it on the BS2, but I have never even tried it with the prop. Here is what I mean:
Counter = 12345
digit0 = 1
digit1 = 2
digit2 = 3
digit3 = 4
digit4 = 5
Here is the kicker, I don't want someone just to post a code and say here you go. How can I learn from that? I just want to know where should I look to figure it out. And any advice that would help.
Thanks
TC

Comments
-Phil
Ok, so you are saying:
counter = 12345
digit0 := counter//10 = 1
digit1 := counter//100 = 2
digit2 := counter//1000 = 3
digit3 := counter//10000 = 4
digit4 := counter//100000 = 5
Cool, I will get back to you when I figure it out. Thank You
Repeat digit from 1 to 5 "something gets value of counter's digit" "load the MAX7219let me know if that is still where I should look. Because I cant figure out how to do what I need to do, yet.
Your parents didn't tell you how to walk, they showed you!
I thought of something like that right as the queen(wife) decided she wanted to go out and get something to eat. Once I get home I will try my idea.
repeat digit from 5 to 1 numb := countr//10 countr := countr/10I agree with you, but we all fell down, cried, then got back up and tried again...... then pooped...
I had to throw that in there. I wanted to be shown just the tools, it works for me to figure out how to use those tools.
pub extract(value, p_buf) | divisor, digit '' Extract (up to) 5-digit value to array at p_buf if (value =< 0) bytefill(p_buf, 0, 5) return if (value => 99999) bytefill(p_buf, 9, 5) return divisor := 10_000 repeat digit from 0 to 4 byte[p_buf][digit] := value / divisor ' extract digit value //= divisor ' remove digit from value divisor /= 10 ' fix divisor for next digitNote that this routine will extract a 5-digit value to a byte array -- not directly to the MAX7219. Why? For flexibility. I would make a MAX7219 method which allows you to point at an array of bytes. That way you can point to DAT tables or calculated arrays (like we are using here). Again, the idea is flexibility. Let's say you had a byte array called digitsbuf; in your program you might have this:
Note that the extract() method looks for upper and lower boundary values -- no need to run the loop if a value is on or past a boundary. In the loop you see the correct order of things: extract a digit with division; update the value (which removes the digit) with modulus; then update the divisor before running again. This order is critical.
Have fun!
repeat temp := counter repeat digit from 3 to 1 numb := temp//10 temp := temp /10 display.Load_7219(digit, numb) !outa[23] counter := counter + 1I only have 3 7-segment displays right now, will have 5 when digi-key order gets here.I have so much more to do, like being able to control the DP, and to be able to control LEDs also digi-key.
I do like your way though, because the LEDs are going to have to do a pattern depending on a value. And it would be easy (I think) to make the pattern and just point to where it is at. I also like that the digits goes from 0 to 4, not like mine where I had to go backwards.
pub extract(value) | divisor, digit '' Extract positive value to segments array if (value =< 0) bytefill(@segments, 0, 8) return if (value => 99_999_999) bytefill(@segments, 9, 8) return divisor := 10_000_000 repeat digit from 7 to 0 segments[digit] := value / divisor ' extract digit value //= divisor ' remove digit from value divisor /= 10 ' fix divisor for next digitThis only extracts the value so you don't have to worry about the size of the display you're using -- a separate method call moves the buffer to the display.
Well, so far your object is working great for displaying numbers.
if DP => 0 and DP =< 7 byte[segments][DP] |= |< 7 else repeat digit from 7 to 0 byte[segments][digit] &= ! |< 7I like to keep things very flexible. Here's are the methods from the object I'm working on that handle the extraction, setting/clearing decimal point, and writing a buffer to any part of the the display. You may wonder why bothering with internal and external buffers. Well, this lets you setup multiple buffers that you can switch back and forth very quickly using the write_buf() method. And it's setup to be very flexible, too, allowing you to write a buffer to any (contiguous) portion of the display.
pub out(reg, value) | bits '' Update register in MAX7219 with value bits.byte[3] := reg ' set register bits.byte[2] := value ' set value repeat 16 ' shift out reg + value outa[mosi] := (bits <-= 1) outa[sck] := 1 outa[sck] := 0 outa[load] := 1 ' load into MAX7219 outa[load] := 0 pub extract(p_buf, value) | divisor, digit '' Extract positive value to array at p_buf '' -- if p_buf is zero, use internal segments array if (p_buf =< 0) p_buf := @segments ' use internal array if (value =< 0) bytefill(p_buf, 0, 8) return if (value => 99_999_999) bytefill(p_buf, 9, 8) return divisor := 10_000_000 repeat digit from 7 to 0 byte[p_buf][digit] := value / divisor ' extract digit value //= divisor ' remove digit from value divisor /= 10 ' fix divisor for next digit pub set_dpoint(p_buf, digit) '' Sets decimal point segment for selected digit register '' -- if p_buf is zero, use internal segments array if (p_buf =< 0) byte[p_buf][digit] |= _DPOINT else segments[digit] |= _DPOINT pub clear_dpoint(p_buf, digit) '' Clears decimal point segment for selected digit register '' -- if p_buf is zero, use internal segments array if (p_buf =< 0) byte[p_buf][digit] &= !_DPOINT else segments[digit] &= !_DPOINT pub write_buf(p_buf, n, reg) '' Writes n (1 to 8) bytes at p_buf to MAX7219 '' -- if p_buf is zero, use internal segments array '' -- reg (1..8) is first register to write '' -- uses existing register modes if (p_buf =< 0) p_buf := @segments ' use internal array n <#= (9 - reg) ' keep n legal repeat n ' write n registers out(reg++, byte[p_buf++])I've attached the full source of the object I'm working on. As I have no hardware setup at the moment, perhaps you could run it for me.
08-DEC-2013 : Corrected error in code identified in post #16 (fix in #17).
I would be honored to.
everything works, but
pub set_dpoint(p_buf, digit) '' Sets decimal point segment for selected digit register '' -- if p_buf is zero, use internal segments array if (p_buf := 0) '<----- had to remove"<" to get it to work byte[p_buf][digit] |= _DPOINT else segments[digit] |= _DPOINTI had to do the same thing to clear_dpoint
I made a demo for it, and everything worked out great. If you are happy with it, please add it to the OBEX.
Thanks for all your help
Video of the demo
pub set_dpoint(p_buf, digit) '' Sets decimal point segment for selected digit register '' -- if p_buf is zero, use internal segments array if (p_buf =< 0) segments[digit] |= _DPOINT ' internal buffer else byte[p_buf][digit] |= _DPOINT ' external buffer pub clear_dpoint(p_buf, digit) '' Clears decimal point segment for selected digit register '' -- if p_buf is zero, use internal segments array if (p_buf =< 0) segments[digit] &= !_DPOINT else byte[p_buf][digit] &= !_DPOINT