Hi Suraj,
It seems you have the correct procedure. You need to keep track of the row number and select the correct five bytes (40 bits) of data from your display array during each interrupt. You'll clock out those 40 bits into the daisy-chained shift registers, blank the display, latch the shift register data onto the outputs, then select the new row to turn the display back on. You do this procedure each interrupt to display a new row.
Regards, Mike
Hi Thanks for the help mike.
From your reply I noticed that you have only 5 registers (5bytes) for the 40 column display not 40 registers like I do.
Table addwf PCL,F
retlw b'000[COLOR="Red"]111[/COLOR]00' ; char "A"
retlw b'00[COLOR="Red"]1[/COLOR]000[COLOR="Red"]1[/COLOR]0'
retlw b'00[COLOR="Red"]11111[/COLOR]0'
retlw b'00[COLOR="Red"]1[/COLOR]000[COLOR="Red"]1[/COLOR]0'
retlw b'00[COLOR="Red"]1[/COLOR]000[COLOR="Red"]1[/COLOR]0'
Table addwf PCL,F
retlw b'00[COLOR="Red"]111111[/COLOR]' ; char "A"
retlw b'0[COLOR="Red"]1[/COLOR]00[COLOR="Red"]1[/COLOR]000'
retlw b'0[COLOR="Red"]1[/COLOR]00[COLOR="Red"]1[/COLOR]000'
retlw b'0[COLOR="Red"]1[/COLOR]00[COLOR="Red"]1[/COLOR]000'
retlw b'00[COLOR="Red"]111111[/COLOR]'
retlw b'00000000'
r08 romchar[] = { 0b0111000, // "0"
0b1000100, //
0b1001100, //
0b1010100, //
0b1100100, //
0b0111000, //
~~~~~~~~~
0b0[COLOR=Red]111[/COLOR]000, // "A"
0b[COLOR=Red]1[/COLOR]000[COLOR=Red]1[/COLOR]00, //
0b[COLOR=Red]1[/COLOR]000[COLOR=Red]1[/COLOR]00, //
0b[COLOR=Red]11111[/COLOR]00, //
0b[COLOR=Red]1[/COLOR]000[COLOR=Red]1[/COLOR]00, //
0b[COLOR=Red]1[/COLOR]000[COLOR=Red]1[/COLOR]00, //
0b[COLOR=Red]1[/COLOR]000[COLOR=Red]1[/COLOR]00, //
0b1111000, // "B"
0b1000100, //
0b1000100, //
0b1111000, //
0b1000100, //
0b1000100, //
0b1111000, //
0b0111000, // "C"
0b1000100, //
0b1000000, //
0b1000000, //
0b1000000, //
0b1000100, //
0b0111000, //
~~~~~~~~~
Gayan,
I use a "character generator" subroutine to place the character pixel bits into the display[] array. This sub' will shift and mask the character pattern as necessary according to an 'htab' value of 0..55. The display[] array maps directly to the display hardware, that is, the display[0..6] bytes are row 0 with bit 7 in the display[0] byte mapping to the left most row 0 pixel and bit 0 in the display[6] byte mapping to the right most row 0 pixel. The ISR automatically loads the shift registers from the display[] array, using bytes in display[0..6] for a row 0 update, or bytes in display[7..13] for a row 1 update, etc..
Regards, Mike
void scroll_left_() // 17 words, 92 cycles
{ u08 i = 7; //
fsr0 = 0x47; // fsr0 = &display[7]
do //
{ asm //
{ rlcf _postdec0,F // scroll row
rlcf _postdec0,F //
rlcf _postdec0,F //
rlcf _postdec0,F //
rlcf _postdec0,F //
rlcf _postdec0,F //
rlcf _postdec0,F //
movlw 15 // prep index for next row
addwf _fsr0l,F //
} //
i--; //
} while(i); //
}
void getromchar(u08 charval) // 31 words, 43 cycles
{ asm //
{ movlw 7 // tblptr = @display + charval * 7
mulwf _charval //
movlw low(romchar) //
addwf _prodl,W //
movwf _tblptrl //
movlw high(romchar) //
addwfc _prodh,W //
movwf _tblptrh //
clrf _tblptru //
tblrd*+ //
movff _tablat,_display+7 // display[7] = romchar[charval*7+0]
tblrd*+ //
movff _tablat,_display+15 // display[15] = romchar[charval*7+1]
tblrd*+ //
movff _tablat,_display+23 // display[23] = romchar[charval*7+2]
tblrd*+ //
movff _tablat,_display+31 // display[31] = romchar[charval*7+3]
tblrd*+ //
movff _tablat,_display+39 // display[39] = romchar[charval*7+4]
tblrd*+ //
movff _tablat,_display+47 // display[47] = romchar[charval*7+5]
tblrd*+ //
movff _tablat,_display+55 // display[55] = romchar[charval*7+6]
}
}
;===========================================================================
;File - Char Generator
;Author - Gayan Soyza
;Date - 08-11-2009
;===========================================================================
;Notes
;
;Character Tables must arrange like this starting from MSB
;Char_A Retlw b'0[COLOR="Red"]111[/COLOR]0000' ; Letter A
; Retlw b'[COLOR="Red"]1[/COLOR]000[COLOR="Red"]1[/COLOR]000'
; Retlw b'[COLOR="Red"]1[/COLOR]000[COLOR="Red"]1[/COLOR]000'
; Retlw b'[COLOR="Red"]11111[/COLOR]000'
; Retlw b'[COLOR="Red"]1[/COLOR]000[COLOR="Red"]1[/COLOR]000'
; Retlw b'[COLOR="Red"]1[/COLOR]000[COLOR="Red"]1[/COLOR]000'
; Retlw b'[COLOR="Red"]1[/COLOR]000[COLOR="Red"]1[/COLOR]000'
;GP registers used
;Htab ; Horizontal Tab (Starting Column of a char)
;Byte_H ; division byteH - Integer
;Byte_L ; division byteL - fraction
;Rotate_Count ; Rotate couns for make masks
;Mask_1 ; mask bits of a char,0 bits will affected by new data
;Mask_2 ; mask bits of a char,0 bits will affected by new data
;Temp_H ; Temperory byteH for char placing from table
;Temp_L ; Temperory byteL for char placing from table
;Pointer ; offset values to table patterns
;----------------------------------------------------------------------------
Char_Generator movwf Htab ; ex: 11th column
movwf Byte_H ;
movlw b'00000011' ; Make default masks first
movwf Mask_1 ; 00000011 11111111
movlw b'11111111' ;
movwf Mask_2
bcf STATUS,C
rrf Byte_H,F ; divide by 8
rrf Byte_L,F
bcf STATUS,C
rrf Byte_H,F
rrf Byte_L,F
bcf STATUS,C
rrf Byte_H,F ; 00000001
rrf Byte_L,F ; 01100000
swapf Byte_L,F
bcf STATUS,C
rrf Byte_L,F ; 00000011
;
movf Byte_L,W ; remainder = 3
btfsc STATUS,Z
goto Char_Place_Loop
movwf Rotate_Count ; 3
;
Make_Masks bsf STATUS,C
rrf Mask_1,F ; 11100000
rrf Mask_2,F ; 01111111
decfsz Rotate_Count,F
goto Make_Masks
;
;-----------------------------------------------------------------------------
;
Char_Place_Loop movf Byte_L,W ;
movwf Rotate_Count
movf Byte_H,W ; position register
addlw 20h
movwf FSR ; add the position from 20h
movf Pointer,W
call Table ; get the character pattern
movwf Temp_H ; store in temp
movf Htab,W ; get column
btfsc STATUS,Z ; is it zero column ?
goto Place_Set_1 ; yes,then no need adjust pattern
Adjust_Pattern bcf STATUS,C ; no,
rrf Temp_H,F
rrf Temp_L,F
decfsz Rotate_Count,F
goto Adjust_Pattern
;
Place_Set_1 movf INDF,W
andwf Mask_1,W
iorwf Temp_H,W
movwf INDF
;
incf FSR,F
Place_Set_2 movf INDF,W
andwf Mask_2,W
iorwf Temp_L,W
movwf INDF
decf FSR,F
;
decfsz Row_Counter,F
goto $+4
movlw .7
movwf Row_Counter
retlw 0x00 ; end of placing a char
movlw .6
addwf FSR,F
incf Pointer,F
goto Char_Place_Loop
Quickly loading 56 bits of column data for each row scan is probably only a problem because you're using 74HC164 shift registers. If you used another serial-to-parallel IC with a <strobe> or <latch> pin then you could take your time loading the shift registers and then simply blank the display (turn off the row) for a couple cycles while you toggle the <strobe> pin to copy the shift register data onto the outputs.I'm doing a research these days what is the speediest way of doing a multiplex routine.
bit mask character pattern
htab % 8 == 0 00000111 11111111 CCCCC000 00000000
htab % 8 == 1 10000011 11111111 0CCCCC00 00000000
htab % 8 == 2 11000001 11111111 00CCCCC0 00000000
htab % 8 == 3 11100000 11111111 000CCCCC 00000000
htab % 8 == 4 11110000 01111111 0000CCCC C0000000
htab % 8 == 5 11111000 00111111 00000CCC CC000000
htab % 8 == 6 11111100 00011111 000000CC CCC00000
htab % 8 == 7 11111110 00001111 0000000C CCCC0000
;
; insert character pattern into display buffer at htab position
;
; void chargen() //
; { MaskL = 0b00000111; // Mask = 00000111 11111111
; MaskR = 0b11111111; //
; Count = htab % 8; // 0..7
; while(Count) //
; { asm //
; { setc //
; rrf MaskL,F //
; rrf MaskR,F //
; } //
; Count--; //
; } //
; fsr = 0x20 + htab / 8; // fsr = &display[0..6]
; row = 0; //
; do //
; { CharL = GetChar(charval,row);
; CharR = 0; //
; Count = htab % 8; // 0..7
; while(Count) //
; { asm //
; { clrc //
; rrf CharL,F //
; rrf CharR,F //
; } //
; Count--; //
; } //
; indf &= MaskL; //
; indf |= CharL; //
; fsr++; //
; indf &= MaskR; //
; indf |= CharR; //
; fsr += 6; // bump index for next row
; row++; //
; } while(row < 7); //
; }
;
CharGen
movlw b'00000011' ; display bit mask
movwf Mask_L ; 00000011 11111111
movlw b'11111111' ;
movwf Mask_R ;
movf Htab,W ; 0..50 max
andlw 7 ; W = Htab % 8 --> 0..7
goto RTest ;
RMask setc ;
rrf Mask_L,F ; rotate 16 bit mask
rrf Mask_R,F ;
RTest addlw -1 ; done rotating?
bnz RMask ; no, branch, else
;
movf Htab,W ; 0..50 max
andlw b'11111000' ; toss b2..b0 fraction bits
movwf FSR ; 0, 8, 16, 24, 32, 40, 48
swapf FSR,F ; pseudo divide-by-16
rlf FSR,W ; preserve Carry and multiply by 2
rlf FSR,F ; FSR = htab / 8
movlw Display ; W = &display[0]
addwf FSR,F ; FSR = &display[0..6]
;
clrf Row ; Row = 0
DoRow call GetChar ; W = getchar(charval,row)
movwf Char_L ;
clrf Char_R ;
movf Htab,W ; 0..50
andlw 7 ; W = Htab % 8 --> 0..7
goto Check ;
Shift clrc ; shift 16 bit pattern
rrf Char_L,F ;
rrf Char_R,F ;
Check addlw -1 ; done shifting?
bnz Shift ; no, branch, else
movf INDF,W ; display[rowindex+htab/8]
andwf Mask_L,W ;
iorwf Char_L,W ;
movwf INDF ;
incf FSR,F ;
movf INDF,W ; display{rowindex+htab/8+1]
andwf Mask_R,W ;
iorwf Char_R,W ;
movwf INDF ;
movlw 6 ;
addwf FSR,F ; bump index for next row
incf Row,F ;
movf Row,W ;
xorlw 7 ; all 7 rows done?
bnz DoRow ; no, branch, else
return ;
Ok, I see what you're doing. That seems like a good method. I had thought you were still using '164 drivers and were concerned about how long you had to blank the display while loading the shift registers with 56 bits of column data during each row update. With the '595 drivers you should only have to blank the display for a few cycles when you latch the shift register data onto the outputs and select the new row and so it shouldn't matter how long you take to actually load the shift registers with 56 bits of data during each interrupt, unless you're trying for some extremely fast refresh rates.I'm placing registers vertically. In ISR routine I track the row position & bit mask the appropriate bit & fill the entire row bit by bit.
Your Character Generator routine for my display buffer method is excellent.
Here's a version of your routine that I just threw together with pseudo C code comments for anyone that's interested in a different perspective, comments, etc.
Mike said:Ok, I see what you're doing. That seems like a good method.
Mike said:How may cycles do you use in your ISR to update a 56 bit row? My 7x55 or 7x56 MacMux design uses 160 cycles (18F') up to about 190 cycles (16F'). If I were to use three seperate pins to load 56 bits into daisy-chained 74HC595 drivers, instead of using the MacMux interface, I can do it in about 250 cycles, maybe faster if I tried.
Jason (AtomSoft),
Did you ever order any of these 0.7-inch 5x7 displays for 69 cents each? They might be a nice candidate for a 7x40 or 7x80 display using my MacMux™ architecture and relatively inexpensive 74HC595 column driver ICs.
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?