A special "Select..Case" needs to drive NIBBLES.

OLDmarty

Senior Member
Hi All,

The following Select..Case snippet from some of my code needs some refinement.
I'm sure it can be replaced by 3 or 4 lines of code with a clever Lookup command, but there some uniqe operations that need to be processed.
Currently, the DataX running through my Select..case code works perfectly, but i'm sure it can be shrunk down to a very efficient procedure instead.

My challenges:
I need to send data (via 8 variables, ROW1 to ROW8) to the Hi2c LED display driver that controls a single 8x8 LED matrix.

The requirement is that when the incoming data (DataX) is '0', then blanks ($00) are sent to the display to blank it out.
When the value '1' arrives, it needs to light the 4 MSB LEDS by sending the data $F0 to the variable 'ROW1' (the MSB nibble)
However, When the value '2' arrives, it needs to light the 4 LSB LEDS by sending the data $0F to the SAME variable 'ROW1' (the LSB nibble)
(essentially treating ROW1 as 2 nibbles being updated).
This procedure then needs to be repeated as data 3,4,5 upto 16 arrives, and send nibbles to the ROW 2 to ROW8 positions.

I'm finding it hard to repeat my DataX twice into the same ROW data by using a Lookup method (so i defaulted to Select..case, which works).
I think i need to separate the odd and even DataX data, so all odds send $F0 to the ROW variable(s), and all evens send $0F to the ROW variable(s).


At the moment, as i receive DataX data from a pot or encoder, my Select..Case quickly gosubs to the "Blankit" routine to blank the entire LED matrix.
Upon return back into the Select..case code, it will then set the nibble data and write it to the LED matrix.

The end effect of doing this, is that by rotating a pot (or encoder) i will see a group of 4 LEDS in a row that moves from the MSB nibble to the LSB nibble position across each of the "ROW1" to ROW8" matrix LEDS, like a travelling line that moves 4-leds-at-a-time) if that makes sense?

At the moment i see Nibble light up from the TOP line of LEDs to the bottom line of LEDs on a single 8x8 matrix.
However, the end plan is to display the nibbles across 8 of the 8x8 matrixs all next to each other, so this nibble of LEDS will step across 8 matrix displays on the top row for example (this is easily handled when i use my existing i2c driver codes in my other project).

I hope this all makes sense? and not clear as mud ;-)

Code:
Symbol DataX = b53    ;Decimal Data (0 to 17, yes, 17 values) is captured from a scaled Analog pot input lookup table, or a rotary encoder/counter value etc.
Symbol _F0 = b54        ;Variable that holds a permanent value $F0
Symbol _0F = b55        ;Variable that holds a permanent value $0F

_F0 = $F0    ;Pre-defined "$F0" buffer (this value NEVER needs to change)
_0F = $0F    ;Pre-defined "$0F" buffer (this value NEVER needs to change)

Do

select case DataX
    case  0 : gosub blankit
    case  1 : gosub blankit : ROW_1 = _F0    ;Set to Pre-defined value of "$F0"
    case  2 : gosub blankit : ROW_1 = _0F    ;Set to Pre-defined value of "$0F"
    case  3 : gosub blankit : ROW_2 = _F0   
    case  4 : gosub blankit : ROW_2 = _0F   
    case  5 : gosub blankit : ROW_3 = _F0   
    case  6 : gosub blankit : ROW_3 = _0F
    case  7 : gosub blankit : ROW_4 = _F0   
    case  8 : gosub blankit : ROW_4 = _0F
    case  9 : gosub blankit : ROW_5 = _F0
    case 10 : gosub blankit : ROW_5 = _0F
    case 11 : gosub blankit : ROW_6 = _F0   
    case 12 : gosub blankit : ROW_6 = _0F   
    case 13 : gosub blankit : ROW_7 = _F0   
    case 14 : gosub blankit : ROW_7 = _0F
    case 15 : gosub blankit : ROW_8 = _F0   
    case 16 : gosub blankit : ROW_8 = _0F
endselect

  
;Write Data to the 8 LED ROWS on the matrix display. (The $00's are just place fillers for a 2nd 8x8 matrix not being used at this time)
Hi2cOUT $00, (ROW_1, $00,  ROW_2, $00,  ROW_3, $00,  ROW_4, $00,  ROW_5, $00,  ROW_6, $00,  ROW_7, $00,  ROW_8, $00)   


Loop
  ;Set ALL the LED rows to OFF, before updating 1 of the LED rows with the $F0 or $0F data pattern.
  blankit:
      ;Set ALL the LED rows to OFF (The $00's are just place fillers for a 2nd 8x8 matrix not being used at this time)
  ROW_1 = $00 : ROW_2 = $00 : ROW_3 = $00 : ROW_4 = $00 : ROW_5 = $00 : ROW_6 = $00 : ROW_7 = $00 : ROW_8 = $00
  return
 

hippy

Senior Member
Assuming ROW_1 to ROW_8 are in sequential byte variables then the following will work. Adjust ADR_ROW_1 to match the byte number of ROW_1 variable. That is, if "Symbol ROW_1 = b23" then you would use "Symbol ADR_ROW_1 = 23".

Code:
Do
  Gosub BlankIt
  If dataX > 0 Then
    bPtr  = dataX - 1 / 2 + ADR_ROW_1
    @bPtr = dataX & 1 * 15 + 1 * $0F
  End If
  Hi2cOUT $00, (ROW_1, $00,  ROW_2, $00 ...
Loop
The bPtr (ROW_X) variable is selected as follows -
Code:
dataX - 1 / 2 + ADR_ROW_1 -> bPtr

1       0   0   23           b23  ROW_1
2       1   0   23           b23  ROW_1
3       2   1   24           b24  ROW_2
4       3   1   24           b24  ROW_2
5       4   2   25           b25  ROW_3
6       5   2   25           b25  ROW_3
And what's assigned is determined as follows -
Code:
dataX & 1 * 15 + 1 * $0F -> @bPtr 

1       1   15   16  $F0    b23 ROW_1 = $F0
2       0    0    1  $0F    b23 ROW_1 = $0F
3       1   15   16  $F0    b24 ROW_2 = $F0   
4       0    0    1  $0F    b24 ROW_2 = $0F
5       1   15   16  $F0    b25 ROW_3 = $F0
6       0    0    1  $0F    b25 ROW_3 = $0F
That "@bPtr = dataX & 1 * 15 + 1 * $0F" could be replaced by "@bPtr = dataX & 1 * 16 Min 1 * $0F" which might be a little quicker to execute.
 

OLDmarty

Senior Member
Assuming ROW_1 to ROW_8 are in sequential byte variables then the following will work. Adjust ADR_ROW_1 to match the byte number of ROW_1 variable. That is, if "Symbol ROW_1 = b23" then you would use "Symbol ADR_ROW_1 = 23".
Thanks so much Hippy,

I'm curious to know if there's a particular reason you wanted to change my "Symbol ROW_1 = b23" to become "Symbol ADR_ROW_1 = 23" ??

Is the "ADR_" some reserved feature that's needed for some other function in your code? or is my use of "ROW" clashing with something reserved in picaxe that i'm not aware of?

Just thought i'd ask ;-)
 

hippy

Senior Member
I'm curious to know if there's a particular reason you wanted to change my "Symbol ROW_1 = b23" to become "Symbol ADR_ROW_1 = 23" ??
It's not changing your definition; it's adding an additional definition which allows 'bPtr' to be pointed at the 'ROW_1' variable. For example, using b23 but your numbers may be different -
Code:
Symbol ADR_ROW_1 = 23

Symbol ROW_1     = b23
Symbol ROW_2     = b24
Symbol ROW_3     = b25
Symbol ROW_4     = b26
Symbol ROW_5     = b27
Symbol ROW_6     = b28
Symbol ROW_7     = b29
Symbol ROW_8     = b30
To set 'bPtr' to point at 'ROW_1' / 'b23' the command to do that has to be -

bPtr = 23

Note the lack of 'b'. If you did include that 'b', as here -

bPtr = b23

That would load what's in 'b23' not the RAM address of 23 which equates to ''b23' when accessed via '@bPtr'. The 'bPtr' would end up pointing at something not intended, and most likely 'b0'.

Because the PICAXE compilers don't have any 'bPtr = AddressOf(b23)' option, that AddressOf(b23) has to be defined explicitly as 23 or defined by a SYMBOL. ADR_ROW_1 serves that purpose.
 
Top