PDA

View Full Version : Joining 5 bit variables and splitting them into 8 bit ones later?



CuriousOne
- 13th December 2020, 06:40
Hello.
I'm using a MAX7219 dot matrix display, 8x8 pixels, 4 daisy chained.
I want to display some numbers on it. I can use 7x7 pixel font, so 4 digits will fit.
But I want to use 6x7 pixel font, so can fit 5 digits on screen.
Each letter graphics are stored in 6 bit codes, like this, for number 8

001110
011011
011011
001110
011011
011011
001110

But data to MAX7219 is being sent into 8 bit increments. So if I send it directly, there will be big gaps and each bit displayed only on single 8x8 matrix. So I need to add these 6 bits to each other, and then split them again into 8 bits. Like this:

001110 001110 001110 001110 should become
00111000 11100011 10001110
Any ideas?

mpgmike
- 14th December 2020, 19:15
Don't quite have the thought fully formed, but I'm thinking along the lines of:


FullDigit VAR LONG
FullDigit = ((Byte1 << 23) + (Byte2 << 17) + (Byte3 << 11)...

This might compact the bits(?)

You need 42 bits, but a LONG only has 32. There's an extra line that would have to be dealt with independently. Again, this isn't a "Solution", just food for thought.

CuriousOne
- 14th December 2020, 20:44
What if I create 32 bit array, write bits in sequence and then read it in appropriate chunks?

mpgmike
- 15th December 2020, 05:55
Something like this?


' 001110 001110 001110 001110
FullDisp VAR LONG
FullDisp.31 = 0
FullDisp.30 = 0
FullDisp.29 = 1
FullDisp.28 = 1
FullDisp.27 = 1
FullDisp.26 = 0
FullDisp.25 = 0
... ... ... ... ... ...

CuriousOne
- 15th December 2020, 07:27
Yes, but have no idea if can use another variable instead of 31 and other digits.
Like displayvar.X=Y

HenrikOlsson
- 15th December 2020, 16:51
I suspect this is what you want:

displayvar.0[X]=Y

But I also suspect we've covered this before so instead of me trying to repeat what's already been covered in detail I just leave it all to Melanie :-)
http://www.picbasic.co.uk/forum/showthread.php?t=544

CuriousOne
- 15th December 2020, 19:39
So it should look like this, right? (have no access to PBP at this moment).


SCREEN32 VAR BIT[32] 'MAIN VARIABLE
LINE1=%10101 'VARIABLE WITH BIT DATA
FOR X=0 TO 4 'READ BITS
SCREEN32[X+1]=LINE1.0(X) 'WRITE INTO ARRAY
NEXT

CuriousOne
- 15th December 2020, 21:40
So here it is, almost finished (not tested in PBP yet, written in notepad).
Digit data are stored as 4 bit width sequences, each char compromising of 4x8 pixels (width & height). They are stored by pairs in eeprom (1st address holds bitmaps for 1 & 2, 2nd address - for 3 & 4 and so on).
This routine should display value of 4 digit CNTR variable on screen. It does that by reading 4 bit graphic data from eeprom, adding 1 space between pixels and assembling into 32 bit array, which later should be cut into 4 bytes and sent to MAX7219. For simplicity, code is shown for sending only 1 line. However, I'm stuck, how to read values from 32 bit array and convert them into bytes.


LINE VAR BIT[32] 'line of MAX7219 buffer
DBIT var byte 'digit bit eeprom address
DOFF var byte 'digit offset 0 for first, 4 for next
DSHF var byte 'Shift value for next digit data
CNTR var word 'Input variable
Y var byte 'Temporary digit variable
X var byte 'digit scan variable
Z var byte 'digit row variable
BT var bit 'bit variable for font hold

' decoder routine
DECODER:
DSHF=0 'reset char shift variable
for x=0 to 3 'read all 4 digits
Y=CNTR DIG X 'EXTRACT VARIABLE DIGIT
IF Y=1 THEN DBIT=0: DOFF=0 'set the font offset
IF Y=2 THEN DBIT=0: DOFF=4
IF Y=3 THEN DBIT=8: DOFF=0
IF Y=4 THEN DBIT=8: DOFF=4
IF Y=5 THEN DBIT=16: DOFF=0
IF Y=6 THEN DBIT=16: DOFF=4
IF Y=7 THEN DBIT=24: DOFF=0
IF Y=8 THEN DBIT=24: DOFF=4
IF Y=9 THEN DBIT=32: DOFF=0
IF Y=0 THEN DBIT=32: DOFF=4

for Z=0 to 4 'read font data and write into rows
READ DBIT+DOFF+Z,BT 'read bit from eeprom
LINE[Z+DSHF]=BT 'write into array
next
DSHF=DSHF+5 'increment char shift variable

'now here should extract bits from array and convert into bytes
'to send to MAX7219, but how?
next

CuriousOne
- 3rd January 2021, 15:36
I decided to return to this code, and have some advancement, but having issues into reading bits from array into an variable.
I have a SCREEN[32] bit array, which should be read into 4 consecutive variables - SEGA, SEGB, SEGC, SEGD.
I know how to access individual bits within variable, but complete byte?

If I understand correctly, the code should look like this


FOR X=0 to 7
SEGA.0(X)=SCREEN[X]
SEGB.0(8+X)=SCREEN[X]
SEGC.0(16+X)=SCREEN[16+X]
SEGD.0(24+X)=SCREEN[24+X]
NEXT


Is this correct?

CuriousOne
- 3rd January 2021, 19:37
Houston, we're having a problem!

Below is the code which works, but it works only if bits in array are aligned to bytes. If I want to shift them to make them less spaced (characters used have 4 pixel width, +1 pixel for spacing), image becomes garbled and shifted in wrong direction, as shown on attached pictures. What I'm doing wrong?



DATA $60,$90,$90,$90,$90,$90,$90,$60 '0 'digits, left justified 4 bits used in each 8 bits
DATA $20,$60,$A0,$20,$20,$20,$20,$F0 '1
DATA $60,$90,$90,$10,$60,$80,$80,$F0 '2
DATA $60,$90,$10,$60,$10,$90,$90,$60 '3
DATA $90,$90,$90,$70,$10,$10,$10,$10 '4
DATA $F0,$80,$80,$E0,$10,$90,$90,$60 '5
DATA $60,$90,$80,$E0,$90,$90,$90,$60 '6
DATA $F0,$10,$10,$20,$20,$40,$40,$40 '7
DATA $60,$90,$90,$60,$90,$90,$90,$60 '8
DATA $60,$90,$90,$70,$10,$90,$90,$60 '9

INVAR=1234
FOR I=0 TO 7 'Read digit data from apropriate positions in EEPROM into own CHAR variables

READ 6+I+8*INVAR DIG 3, CHAR1
READ 6+I+8*INVAR DIG 2, CHAR2
READ 6+I+8*INVAR DIG 1, CHAR3
READ 6+I+8*INVAR DIG 0, CHAR4

FOR Y=0 TO 7 'write CHAR DATA INTO ARRAY WITH OFFSET
SCREEN32[Y]=CHAR1.0(Y)
SCREEN32[Y+8]=CHAR2.0(Y) 'OFSETS ARE SET HERE
SCREEN32[Y+16]=CHAR3.0(Y)
SCREEN32[Y+24]=CHAR4.0(Y)
NEXT

'read array data into 8 bit variables

FOR C=0 to 7
SEGA.0(C)=SCREEN32[C]
SEGB.0(C)=SCREEN32[8+C]
SEGC.0(C)=SCREEN32[16+C]
SEGD.0(C)=SCREEN32[24+C]
NEXT

'WRITE ARRAY DATA INTO DISPLAY AND GO TO NEXT LINE
LOW LOAD
shiftout datapin,clockpin,1,[1+I, SEGA]
shiftout datapin,clockpin,1,[1+I, SEGB]
shiftout datapin,clockpin,1,[1+I, SEGC]
shiftout datapin,clockpin,1,[1+I, SEGD]
HIGH LOAD

NEXT
END


8998

8999

richard
- 4th January 2021, 01:56
you are dealing with a matrix that fills like this


9001
its not a particularly easy format to leverage font images that traverse cells , and you cannot read back the data from the matrix
to make life easy i would make a memory array [frame buffer] mapped to the matrix like this


9000


it's then quite straight forward to overlay a font chr into any location
and then create a simple routine to write the frame buffer to the display
in the bit order the matrix demands

CuriousOne
- 4th January 2021, 06:51
Well, I already have buffer, but 32x1 pixels in size, because the data is sent to display line by line.
But the problem is different, I can't understand why this works only per 8 bit: SCREEN32[Y+8]=CHAR2.0(Y) - if I enter any other number instead of 8, which is not multiple of 8, say 5 or 17, everything becomes garbled, while it should not. So, maybe I'm writing in array incorrectly?

I was able to solve this problem by replacing array with string of Boolean logic operations, but I'd like to keep array, because later I want to display more letters, with variable width...


char1=char1 | char2>>5
char2=char2 <<3 | char3>>2
char2=char2 | char4>>7
char3=char4<<1
char4=0

CuriousOne
- 4th January 2021, 06:53
Oh, and by the way, is there any possibility to increase SPI speed? I'm running 16F886 @ 8mhz, and update rate is clearly not good - forget about scrolling letters and other stuff like that.

richard
- 4th January 2021, 07:07
Oh, and by the way, is there any possibility to increase SPI speed? I'm running 16F886 @ 8mhz, and update rate is clearly not good - forget about scrolling letters and other stuff like that.

yes don't use shiftout, on a chip that has a mssp module it's an order of magnitude or two slower than spi
its like having a dog and barking yourself



Well, I already have buffer, but 32x1 pixels in size, because the data is sent to display line by line.

yet characters persist over 8 lines and you are ignoring that present data, furthermore there is no way to recover that data from the chip
you figure it out

richard
- 4th January 2021, 07:46
after some thought ,


Well, I already have buffer, but 32x1 pixels in size, because the data is sent to display line by line.
But the problem is different, I can't understand why this works only per 8 bit: SCREEN32[Y+8]=CHAR2.0(Y) - if I enter any other number instead of 8, which is not multiple of 8, say 5 or 17, everything becomes garbled, while it should not. So, maybe I'm writing in array incorrectly?


i assume SCREEN32 is your 32 bit array ,
SCREEN32[Y+8] is then a complete nonsense as the only valid locations are 0 to 3

similarly wtf is char2 ? if its a byte then
CHAR2.0(Y) a valid y value can only be 0 to 7

then we have this, wtf is char1 a byte a word an array ? , a pointless snippet

char1=char1 | char2>>5
char2=char2 <<3 | char3>>2
char2=char2 | char4>>7
char3=char4<<1char4=0

CuriousOne
- 4th January 2021, 10:44
Yes, SCREEN32 is 32 bit array.
And why locations only can be from 0 to 3 ?
There are 32 bits, or what you want to say, that is not possible to write into specific bit of bit array?

I'm reading a bit from variable and writing it into bit of an array, to later read bits as needed.

richard
- 4th January 2021, 10:57
thats what happens with snippets ,there is no context

SCREEN32 var bit[32] would have made it clear



I'm reading a bit from variable and writing it into bit of an array, to later read bits as needed.
good luck

richard
- 4th January 2021, 11:16
proof of concept
btw i like your font it looks better than my 6x5 one

sorry for shaky vid , was trying to use mouse while steering phone , failed both accounts
https://youtu.be/DanYYBoVOBU

CuriousOne
- 4th January 2021, 12:17
Well, I'm designing fonts for last 30 years, so no surprise mine is better :D
proof of concept of what?
Any code was posted?

richard
- 4th January 2021, 12:42
basically this , modded slightly for the 4x8 font
http://www.picbasic.co.uk/forum/showthread.php?t=24171

CuriousOne
- 4th January 2021, 14:04
And this is proof of my code working :D
So if I understood correctly, there is no HSHIFTOUT statement, like HSEROUT ?

9002

CuriousOne
- 5th January 2021, 17:12
But I still have an issue - why reading from a bit array from arbitrary position (not byte justified) returns garbage?

richard
- 6th January 2021, 06:13
why reading from a bit array from arbitrary position (not byte justified) returns garbage?

a minimal, complete and verifiable example MCVE
https://stackoverflow.com/help/minimal-reproducible-example


here is one that shows no problem at all pbp3, examination of lst file confirms reservation of the 4 bytes required for the bit array
if there was ever any doubt


; pbp3 16f1825
define OSC 32
#CONFIG
__config _CONFIG1, _FOSC_INTOSC & _CP_OFF & _WDTE_OFF & _PWRTE_ON & _MCLRE_ON & _CLKOUTEN_OFF
__config _CONFIG2, _PLLEN_ON & _LVP_OFF
#ENDCONFIG


DEFINE DEBUG_REG PORTA
DEFINE DEBUG_BIT 0
DEFINE DEBUG_BAUD 9600
DEFINE DEBUG_MODE 0



OSCCON=$70
ANSELA=0
ANSELC=0

barray var bit[32]
bbyte var byte ext
another var word
cnt var byte
tst var bit
more var byte
@bbyte = PBA01
clear


bbyte[0]=5
bbyte[1]=$55

lata.0=1
pause 2000
Debug "Start",13 ,10
for cnt=31 to 0 step -1
Debug #barray[cnt]
next
Debug " array by bit",13 ,10
for cnt =3 to 0 step -1
Debug bin8 bbyte[cnt]
next

barray[11] =1
Debug " array by byte in bin",13,10,"set bit 11",13 ,10
for cnt=31 to 0 step -1
Debug #barray[cnt]
next
Debug 13 ,10
for cnt =3 to 0 step -1
Debug bin8 bbyte[cnt]
next

bbyte[3] =255
Debug 13 ,10,"set byte 3",13 ,10
for cnt=31 to 0 step -1
Debug #barray[cnt]
next
Debug 13 ,10
for cnt =3 to 0 step -1
Debug bin8 bbyte[cnt]
next

barray[11] =0
Debug 13 ,10,"clr bit 11",13 ,10
for cnt=31 to 0 step -1
Debug #barray[cnt]
next
Debug 13 ,10
for cnt =3 to 0 step -1
Debug bin8 bbyte[cnt]
next

bbyte[3] =0
Debug 13 ,10,"clr byte 3",13 ,10
for cnt=31 to 0 step -1
Debug #barray[cnt]
next
Debug 13 ,10
for cnt =3 to 0 step -1
Debug bin8 bbyte[cnt]
next

printout

Start
00000000000000000101010100000101 array by bit
00000000000000000101010100000101 array by byte in bin
set bit 11
00000000000000000101110100000101
00000000000000000101110100000101
set byte 3
11111111000000000101110100000101
11111111000000000101110100000101
clr bit 11
11111111000000000101010100000101
11111111000000000101010100000101
clr byte 3
00000000000000000101010100000101
00000000000000000101010100000101

CuriousOne
- 6th January 2021, 21:08
Will take a look tomorrow...
Meanwhile, added decimal point, C and F sign support...