Initial check in

This commit is contained in:
2026-01-03 19:05:48 +01:00
commit 1254878a31
253 changed files with 30484 additions and 0 deletions
+552
View File
@@ -0,0 +1,552 @@
PUBLIC jtag_init
PUBLIC _jtag_set_state
PUBLIC _jtag_set_enddr
PUBLIC _jtag_set_endir
PUBLIC jtag_get_enddr
PUBLIC jtag_get_endir
PUBLIC _jtag_tck
PUBLIC _jtag_xfer
; PUBLIC _jtag_prgn
; EXTRN code(_lcd_putx2)
JTAG_CODE SEGMENT CODE
JTAG_TABLES SEGMENT CODE
JTAG_FLAGS SEGMENT BIT
JTAG_DATA SEGMENT DATA
; -----------------------------------------------------------------------------
; LatticeVME TAP state values
; -----------------------------------------------------------------------------
TS_RESET EQU 0
TS_IDLE EQU 1
TS_IRPAUSE EQU 2
TS_DRPAUSE EQU 3
TS_IRSHIFT EQU 4
TS_DRSHIFT EQU 5
TS_DRCAPT EQU 6
TS_IREXIT1 EQU 7
TS_DREXIT1 EQU 8
; -----------------------------------------------------------------------------
$IF(BOARD_DSO)
IOA EQU 0x80
JTAG_TCK BIT IOA.0
JTAG_TMS BIT IOA.1
JTAG_TDI BIT IOA.3
JTAG_TDO BIT IOA.7
$ELSEIF(BOARD_JTAG)
IOA EQU 0x80
JTAG_TCK BIT IOA.0
JTAG_TMS BIT IOA.1
JTAG_TDI BIT IOA.7
JTAG_TDO BIT IOA.3
JTAG_ENA BIT IOA.4
$ELSEIF(BOARD_CF1)
IOA EQU 0x80
IOC EQU 0A0h
JTAG_TCK BIT IOC.0
JTAG_TMS BIT IOC.1
JTAG_TDI BIT IOC.2
JTAG_TDO BIT IOC.3
JTAG_PRGn BIT IOC.4
$ELSE
adad
$ENDIF
RSEG JTAG_FLAGS
fl_last: DBIT 1
RSEG JTAG_DATA
tap_endir: DS 1
tap_enddr: DS 1
tap_state: DS 1
; =============================================================================
; void jtag_init(void)
; =============================================================================
RSEG JTAG_CODE
$REGUSE jtag_init(R7)
jtag_init:
mov tap_enddr,#TS_IDLE
mov tap_endir,#TS_IDLE
mov tap_state,#TS_DRSHIFT
mov R7,#TS_RESET
ljmp _jtag_set_state
; =============================================================================
; void jtag_tck( WORD clk)
;
; input
; R7 = LSB(clk)
; R6 = MSB(clk)
; =============================================================================
$REGUSE _jtag_tck(B,R6,R7)
; -----------------------------------------------------------------
; check parameters
; -----------------------------------------------------------------
_jtag_tck: cjne R7,#0,CK0 ; if length = 0 then
cjne R6,#0,CK0 ; return;
ret ;
; -----------------------------------------------------------------
; calculate pulse count
; -----------------------------------------------------------------
CK0: cjne R6,#0,CK1 ; if length < 256 then
; begin
mov B,R7 ; count := R7;
mov R7,#0 ; length := 0;
sjmp CK2 ; end
;
; else begin
CK1: mov B,#0 ; count := 256;
dec R6 ; length := length -256
; end;
; -----------------------------------------------------------------
; generate pulses (max 256 in one chunk) with 1 MHz frequency.
; -----------------------------------------------------------------
; do
CK2:
setb JTAG_TCK ; TCK 1->0
; nop ; for 500 kHz remove comment
; nop ;
; nop ;
; nop ;
; nop ;
; nop ;
clr JTAG_TCK ; TCK 0 ->1
; nop ; for 500 kHz remove comment
; nop ;
; nop ;
; nop ;
; nop ;
; nop ;
djnz B,CK2 ; count := count -1;
; while count > 0;
; -----------------------------------------------------------------
; repeat until length = 0
; -----------------------------------------------------------------
sjmp _jtag_tck
; =============================================================================
; The ENDDR and ENDIR commands specify the IEEE 1149.1 stable state that the
; IEEE 1149.1 bus will be forced to at the conclusion of a DR or IR scan,
; respectively. Once specified, the ENDDR/ENDIR commands remain in force until
; overriden by another ENDDR or ENDIR command. At startup, ENDDR and ENDIR are
; both set to IDLE. Valid states are IRPAUSE, DRPAUSE, RESET, and IDLE.
; =============================================================================
; =============================================================================
; BYTE jtag_get_enddr();
; =============================================================================
$REGUSE jtag_get_enddr()
jtag_get_enddr:
mov R7, tap_enddr
ret
; =============================================================================
; BYTE jtag_get_endir();
; =============================================================================
$REGUSE jtag_get_endir()
jtag_get_endir:
mov R7, tap_endir
ret
; =============================================================================
; bit jtag_set_enddr(BYTE state);
; =============================================================================
$REGUSE _jtag_set_enddr()
_jtag_set_enddr:
lcall jtag_chk_endstate
jnc DRX
mov tap_enddr,R7
DRX: ret
; =============================================================================
; bit jtag_set_endir(BYTE state);
; =============================================================================
$REGUSE _jtag_set_endir()
_jtag_set_endir:
lcall jtag_chk_endstate
jnc IRX
mov tap_endir,R7
IRX: ret
; =============================================================================
; bit jtag_chk_endstate(BYTE state);
; =============================================================================
jtag_chk_endstate:
clr C
cjne R7,#TS_DRPAUSE,C0
sjmp C8
C0: cjne R7,#TS_IRPAUSE,C1
sjmp C8
C1: cjne R7,#TS_RESET,C2
sjmp C8
C2: cjne R7,#TS_IDLE,C9
C8: setb C
C9: ret
; =============================================================================
; void jtag_xfer_chunk(BYTE length, BYTE last)
;
; input:
; R7 = length (bit count) 0 = 256
;
; dptr = buffer
;
; used:
; A = data / tap_state
; B = bit counter
; C = temp bit
; =============================================================================
; -----------------------------------------------------------------
; process length-1 bits
; -----------------------------------------------------------------
;X0: clr JTAG_TCK ; TCK 1->0
; mov C,JTAG_TDO ; get TDO into C
X0:
mov C,JTAG_TDO ; get TDO into C
rlc A ;
mov JTAG_TDI,C ; put TDI from C
setb JTAG_TCK ; TCK 0->1
nop ;
nop ;
clr JTAG_TCK ; TCK 1->0
; ---------------------------------
djnz B,X2 ; if bit_counter = 1 then
; begin
movx @dptr,A ; dptr^ := a;
inc dptr ; inc(dptr);
jtag_xfer_chunk:
movx A,@dptr ; a := dptr^;
mov B,#8 ; bit_counter := 8
; end;
X2: djnz R7,X0 ; if length > 1 then
; loop;
; -----------------------------------------------------------------
; process last bit
; -----------------------------------------------------------------
mov C,JTAG_TDO ; get TDO into C
rlc A ;
mov JTAG_TDI,C ; put TDI from C
jnb fl_last,X3 ; if this is the last chunk
setb JTAG_TMS ; then exit from xxSHIFT
X3: ;nop
setb JTAG_TCK ; TCK 0->1
nop
clr JTAG_TCK ; TCK 1->0
; -----------------------------------------------------------------
; if less then 8 bits has arrived, then fill the rest of A with
; zero bits.
; -----------------------------------------------------------------
djnz B,X4 ; while bit_counter <> 1 then
ljmp X5 ; begin
; C := 0;
X4: clr C ; A := (A::C shl 1);
rlc A ; dec(bit_counter);
djnz B,X4 ; end;
X5: movx @dptr,A ; dptr^ := a;
inc dptr ; inc(dptr);
; -----------------------------------------------------------------
; move to state ENDIR/ENDDR if this was the last chunk
; -----------------------------------------------------------------
jnb fl_last,X9 ; if not the last chunk then
; return
mov A,tap_state ; get actual state which is
; - DRSHIFT or
; - IRSHIFT
cjne A,#TS_DRSHIFT,X8 ; if it is DRSHIFT then
mov tap_state,#TS_DREXIT1 ; set actual state to DREXIT1
mov R7,tap_enddr ; set target state to "ENDDR"
jmp _jtag_set_state ; execute transition
X8: cjne A,#TS_IRSHIFT,X9 ; if it is IRSHIFT then
mov tap_state,#TS_IREXIT1 ; set actual state to IREXIT1
mov R7,tap_endir ; set target state to "ENDIR"
jmp _jtag_set_state ; execute transition
X9: ret
; =============================================================================
; jtag_xfer( BYTE xdata *buffer, WORD length, BYTE last);
;
; R7 = LSB(buffer)
; R6 = MSB(buffer)
;
; R5 = LSB(length in bits); // length mod 256
; R4 = MSB(length in bits); // length div 256
;
; R3 = last
;
; =============================================================================
$REGUSE _jtag_xfer(A,B,C,R4,R6,R7,DPTR)
; -----------------------------------------------------------------
; check parameters
; -----------------------------------------------------------------
_jtag_xfer: cjne R5,#0,RW ; if length = 0 then
cjne R4,#0,RW ; return;
ret ;
; -----------------------------------------------------------------
; initialize variables
; -----------------------------------------------------------------
RW: mov DPL,R7 ; dptr := @buffer;
mov DPH,R6 ;
;
clr fl_last ; fl_last := false
; -----------------------------------------------------------------
; process data in 256 bit (32 bytes) chunks
; -----------------------------------------------------------------
; while true do
; begin
RW0: cjne R4,#0,RW2 ; if length div 256 = 0 then
; begin
;
mov A,R5 ; R7 := length mod 256;
mov R7,A ;
;
RW1: mov A,R3 ; A := last
rrc A ; C := last
mov fl_last,C ; fl_last := C
;
ljmp jtag_xfer_chunk ; jtag_rdwr_chunk(len,last);
; break
; end
;
; else begin
RW2: mov R7,#0 ; R7 := 256;
dec R4 ; dec(length,256);
;
cjne R4,#0,RW3 ; if length div 256 = 0 then
cjne R5,#0,RW3 ; if length mod 256 = 0 then
sjmp RW1 ; goto RW1;
;
;
RW3: lcall jtag_xfer_chunk ; jtag_rdwr_chunk(256,false);
sjmp RW0 ; end
; end;
; =============================================================================
; jtag_state( BYTE state)
;
;
; input
; R7 - new state
;
; note:
; Reset always does full 5 bits stream, because we cannot be sure the
; actual state. It will bring the JTAG state machine into a known state.
; =============================================================================
$REGUSE _jtag_set_state(A,B,C,DPTR)
_jtag_set_state:
setb JTAG_TDI
; -------------------------------------
; Get the pattern table for the current
; tap state into DPTR.
; -------------------------------------
mov dptr,#x_table
mov a,tap_state
rl a
movc a,@a+dptr
mov b,a
mov a,tap_state
rl a
inc a
movc a,@a+dptr
mov dpl,a
mov dph,b
; -------------------------------------
; fetch the TMS pattern and pattern
; length to move to new state.
; -------------------------------------
mov a,r7 ; get TMS pattern length into B
rl a ;
inc a ;
movc a,@a+dptr ;
mov b,a ;
cjne A,#0,L101 ; if pattern length = 0 then
ret ; no new state is specified, so return
L101: mov a,r7 ; get TMS pattern into A
rl a ;
movc a,@a+dptr ;
; -------------------------------------
; step out the TMS pattern
; -------------------------------------
loop: rlc a ; get TMS bit into C flag
mov JTAG_TMS,C ; output TMS
setb JTAG_TCK ; set TCK
nop
clr JTAG_TCK ; clear TCK
djnz b,loop ;
; -------------------------------------
; set new state as current
; -------------------------------------
mov tap_state,r7
ret
; =============================================================================
; tap state transition tables
; =============================================================================
RSEG JTAG_TABLES
x_table: DW x_reset
DW x_idle
DW x_irpause
DW x_drpause
DW x_irshift
DW x_drshift
DW x_drcapture
DW x_irexit1
DW x_drexit1
x_reset: ; -------------------------------------------------------
DB 11111000b,5 ; reset -> reset : 11111
DB 00000000b,1 ; reset -> idle : 0
DB 01101000b,6 ; reset -> irpause : 011010
DB 01010000b,5 ; reset -> drpause : 01010
DB 01100000b,5 ; reset -> irshift : 01100
DB 01000000b,4 ; reset -> drshift : 0100
DB 01000000b,3 ; reset -> drcapture : 010
x_idle: ; -------------------------------------------------------
DB 11111000b,5 ; reset -> reset : 11111
DB 00000000b,1 ; idle -> idle : 0
DB 11010000b,5 ; idle -> irpause : 11010
DB 10100000b,4 ; idle -> drpause : 1010
DB 11000000b,4 ; idle -> irshift : 1100
DB 10000000b,3 ; idle -> drshift : 100
DB 10000000b,2 ; idle -> drcapture : 10
x_irpause: ; -------------------------------------------------------
DB 11111000b,5 ; irpause -> reset : 11111
DB 11000000b,3 ; irpause -> idle : 110
DB 11110100b,7 ; irpause -> irpause : 1111010
DB 11101000b,6 ; irpause -> drpause : 111010
DB 10000000b,2 ; irpause -> irshift : 10
DB 11100000b,5 ; irpause -> drshift : 11100
DB 11100000b,4 ; irpause -> drcapture : 1110
x_drpause: ; -------------------------------------------------------
DB 11111000b,5 ; drpause -> reset : 11111
DB 11000000b,3 ; drpause -> idle : 110
DB 11110100b,7 ; drpause -> irpause : 1111010
DB 11101000b,6 ; drpause -> drpause : 111010
DB 11110000b,6 ; drpause -> irshift : 111100
DB 10000000b,2 ; drpause -> drshift : 10
DB 11100000b,4 ; drpause -> drcapture : 1110
x_irshift: ; -------------------------------------------------------
DB 11111000b,5 ; irshift -> reset : 11111
DB 11000000b,3 ; irshift -> idle : 110
DB 10000000b,2 ; irshift -> irpause : 10
DB 11101000b,6 ; irshift -> drpause : 111010
DB 00000000b,0 ; irshift -> irshift : -
DB 11100000b,5 ; irshift -> drshift : 11100
DB 11100000b,4 ; irshift -> drcapture : 1110
x_drshift: ; -------------------------------------------------------
DB 11111000b,5 ; drshift -> reset : 11111
DB 11000000b,3 ; drshift -> idle : 110
DB 11110100b,7 ; drshift -> irpause : 1111010
DB 10000000b,2 ; drshift -> drpause : 10
DB 11110000b,6 ; drshift -> irshift : 111100
DB 00000000b,0 ; drshift -> drshift : -
DB 11100000b,4 ; drshift -> drcapture : 1110
x_drcapture:; -------------------------------------------------------
DB 11111000b,5 ; drcapture -> reset : 11111
DB 11000000b,3 ; drcapture -> idle : 110
DB 11110100b,7 ; drcapture -> irpause : 1111010
DB 10000000b,2 ; drcapture -> drpause : 10
DB 11110000b,6 ; drcapture -> irshift : 111100
DB 00000000b,1 ; drcapture -> drshift : 0
DB 00000000b,0 ; drcapture -> drcapture: -
x_irexit1: ; -------------------------------------------------------
DB 11111000b,5 ; reset -> reset : 11111
DB 10000000b,2 ; irexit1 -> idle : 10
DB 00000000b,1 ; irexit1 -> irpause : 0
DB 11010000b,5 ; irexit1 -> drpause : 11010
DB 01000000b,3 ; irexit1 -> irshift : 010
DB 11000000b,4 ; irexit1 -> drshift : 1100
DB 11000000b,3 ; irexit1 -> drcapture : 110
x_drexit1: ; -------------------------------------------------------
DB 11111000b,5 ; reset -> reset : 11111
DB 10000000b,2 ; drexit1 -> idle : 10
DB 11101000b,6 ; drexit1 -> irpause : 111010
DB 00000000b,1 ; drexit1 -> drpause : 0
DB 11100000b,5 ; drexit1 -> irshift : 11100
DB 01000000b,3 ; drexit1 -> drshift : 010
DB 11000000b,3 ; drexit1 -> drcapture : 110
END
+65
View File
@@ -0,0 +1,65 @@
#include <fx2.h>
#include <fx2_regs.h>
extern void FX2_Delay( WORD ms);
extern void lcd_44780_write_ctrl( unsigned char value);
extern void lcd_44780_write_data( unsigned char value);
extern void lcd_44780_write_led( BYTE n, BYTE v);
code BYTE bin2hex[16] =
{
0x30, 0x31, 0x32, 0x33, 0x34, // 0 - 4
0x35, 0x36, 0x37, 0x38, 0x39, // 5 - 9
0x41, 0x42, 0x43, 0x44, 0x45, 0x46 // A - F
};
void lcd_44780_init()
{
lcd_44780_write_ctrl( 0x38); FX2_Delay(5);
lcd_44780_write_ctrl( 0x0F); FX2_Delay(5);
lcd_44780_write_ctrl( 0x01); FX2_Delay(5);
lcd_44780_write_ctrl( 0x06); FX2_Delay(5);
lcd_44780_write_ctrl( 0x0C); FX2_Delay(1);
lcd_44780_write_ctrl( 0x40 | 0x80); FX2_Delay(1);
}
void lcd_44780_gotoxy( BYTE x, BYTE y)
{
BYTE cmd;
cmd = 0x80;
cmd = cmd | ((y & 0x01) << 6);
cmd = cmd | ((x & 0x07));
lcd_44780_write_ctrl(cmd);
FX2_Delay(1);
}
void lcd_44780_putled( BYTE n, BYTE v)
{
lcd_44780_write_led(n,v);
}
void lcd_44780_putc( char c)
{
lcd_44780_write_data( c);
FX2_Delay(1);
}
void lcd_44780_puts( char *s)
{
if(s)
while( *s)
lcd_44780_putc(*s++);
}
void lcd_44780_putx2( BYTE x)
{
BYTE x1 = bin2hex[(x >> 4) & 0x0F];
BYTE x2 = bin2hex[(x >> 0) & 0x0F];
lcd_44780_write_data(x1); FX2_Delay(2);
lcd_44780_write_data(x2); FX2_Delay(2);
}
+421
View File
@@ -0,0 +1,421 @@
#include <fx2.h>
#include <fx2_regs.h>
#include <lcd\lcd_7565r.h>
extern void lcd_7565r_init(void);
extern void lcd_7565r_deactivate(void);
extern void lcd_7565r_send( BYTE, bit);
static void st7565r_cmd_lcdbias( BYTE);
static void st7565r_cmd_adcsel( BYTE);
static void st7565r_cmd_coms( BYTE);
static void st7565r_cmd_v0reg( BYTE);
static void st7565r_cmd_evol( BYTE);
static void st7565r_cmd_boost( BYTE);
static void st7565r_cmd_power( BYTE);
code BYTE bin2hex[16] =
{
0x10, 0x11, 0x12, 0x13, 0x14, // 0 - 4
0x15, 0x16, 0x17, 0x18, 0x19, // 5 - 9
0x21, 0x22, 0x23, 0x24, 0x25, 0x26 // A - F
};
code BYTE ascii[95][5] =
{
{0x00, 0x00, 0x00, 0x00, 0x00}, //0x20 space
{0x00, 0x00, 0xbe, 0x00, 0x00}, //0x21 !
{0x00, 0x0e, 0x00, 0x0e, 0x00}, //0x22 "
{0x28, 0xfe, 0x28, 0xfe, 0x28}, //0x23 #
{0x48, 0x54, 0xfe, 0x54, 0x24}, //0x24 $
{0x46, 0x26, 0x10, 0xc8, 0xc4}, //0x25 %
{0x6c, 0x92, 0xaa, 0x44, 0xa0}, //0x26 &
{0x00, 0x0a, 0x06, 0x00, 0x00}, //0x27 '
{0x00, 0x38, 0x44, 0x82, 0x00}, //0x28 (
{0x00, 0x82, 0x44, 0x38, 0x00}, //0x29 )
{0x28, 0x10, 0x7c, 0x10, 0x28}, //0x2a *
{0x10, 0x10, 0x7c, 0x10, 0x10}, //0x2b +
{0x00, 0xa0, 0x60, 0x00, 0x00}, //0x2c ,
{0x10, 0x10, 0x10, 0x10, 0x10}, //0x2d -
{0x00, 0xc0, 0xc0, 0x00, 0x00}, //0x2e .
{0x40, 0x20, 0x10, 0x08, 0x04}, //0x2f /
{0x7c, 0xA2, 0x92, 0x8A, 0x7c}, //0x30 0
{0x00, 0x84, 0xfe, 0x80, 0x00}, //0x31 1
{0x84, 0xc2, 0xa2, 0x92, 0x8c}, //0x32 2
{0x42, 0x82, 0x8a, 0x96, 0x62}, //0x33 3
{0x30, 0x28, 0x24, 0xfe, 0x20}, //0x34 4
{0x4e, 0x8a, 0x8a, 0x8a, 0x72}, //0x35 5
{0x78, 0x94, 0x92, 0x92, 0x60}, //0x36 6
{0x02, 0xe2, 0x12, 0x0a, 0x06}, //0x37 7
{0x6c, 0x92, 0x92, 0x92, 0x6c}, //0x38 8
{0x0c, 0x92, 0x92, 0x52, 0x3c}, //0x39 9
{0x00, 0x6c, 0x6c, 0x00, 0x00}, //0x3a :
{0x00, 0xac, 0x6c, 0x00, 0x00}, //0x3b ;
{0x10, 0x28, 0x44, 0x82, 0x00}, //0x3c <
{0x28, 0x28, 0x28, 0x28, 0x28}, //0x3d =
{0x00, 0x82, 0x44, 0x28, 0x10}, //0x3e >
{0x04, 0x02, 0xa2, 0x12, 0x0c}, //0x3f ?
{0x74, 0x92, 0xf2, 0x82, 0x7c}, //0x40 @
{0xfc, 0x12, 0x12, 0x12, 0xfc}, //0x41 A
{0xfe, 0x92, 0x92, 0x92, 0x6c}, //0x42 B
{0x7c, 0x82, 0x82, 0x82, 0x44}, //0x43 C
{0xfe, 0x82, 0x82, 0x44, 0x38}, //0x44 D
{0xfe, 0x92, 0x92, 0x92, 0x82}, //0x45 E
{0xfe, 0x12, 0x12, 0x12, 0x02}, //0x46 F
{0x7c, 0x82, 0x82, 0xa2, 0x64}, //0x47 G
{0xfe, 0x10, 0x10, 0x10, 0xfe}, //0x48 H
{0x00, 0x82, 0xfe, 0x82, 0x00}, //0x49 I
{0x40, 0x80, 0x82, 0x7e, 0x02}, //0x4a J
{0xfe, 0x10, 0x28, 0x44, 0x82}, //0x4b K
{0xfe, 0x80, 0x80, 0x80, 0x80}, //0x4c L
{0xfe, 0x04, 0x18, 0x04, 0xfe}, //0x4d M
{0xfe, 0x0c, 0x10, 0x60, 0xfe}, //0x4e N
{0x7c, 0x82, 0x82, 0x82, 0x7c}, //0x4f O
{0xfe, 0x12, 0x12, 0x12, 0x0c}, //0x50 P
{0x7c, 0x82, 0xa2, 0x42, 0xbc}, //0x51 Q
{0xfe, 0x12, 0x32, 0x52, 0x8c}, //0x52 R
{0x4c, 0x92, 0x92, 0x92, 0x64}, //0x53 S
{0x02, 0x02, 0xfe, 0x02, 0x02}, //0x54 T
{0x7e, 0x80, 0x80, 0x80, 0x7e}, //0x55 U
{0x3e, 0x40, 0x80, 0x40, 0x3e}, //0x56 V
{0x7e, 0x80, 0x70, 0x80, 0x7e}, //0x57 W
{0xc6, 0x28, 0x10, 0x28, 0xc6}, //0x58 X
{0x0e, 0x10, 0xe0, 0x10, 0x0e}, //0x59 Y
{0xc2, 0xa2, 0x92, 0x8a, 0x86}, //0x5a Z
{0x00, 0xfe, 0x82, 0x82, 0x00}, //0x5b [
{0x04, 0x08, 0x10, 0x20, 0x40}, //0x5c backslash
{0x00, 0x82, 0x82, 0xfe, 0x00}, //0x5d ]
{0x08, 0x04, 0x02, 0x04, 0x08}, //0x5e ^
{0x80, 0x80, 0x80, 0x80, 0x80}, //0x5f _
{0x00, 0x02, 0x04, 0x08, 0x00}, //0x60 `
{0x40, 0xa8, 0xa8, 0xa8, 0xf0}, //0x61 a
{0xfe, 0x88, 0x88, 0x88, 0x70}, //0x62 b
{0x70, 0x88, 0x88, 0x88, 0x50}, //0x63 c
{0x70, 0x88, 0x88, 0x88, 0xfe}, //0x64 d
{0x70, 0xa8, 0xa8, 0xa8, 0xb0}, //0x65 e
{0x10, 0xfc, 0x12, 0x02, 0x04}, //0x66 f
{0x10, 0xa8, 0xa8, 0xa8, 0x78}, //0x67 g
{0xfe, 0x08, 0x08, 0x08, 0xf0}, //0x68 h
{0x00, 0x08, 0xfa, 0x00, 0x00}, //0x69 i
{0x40, 0x80, 0x88, 0x7a, 0x00}, //0x6a j
{0xfe, 0x20, 0x50, 0x88, 0x00}, //0x6b k
{0x00, 0x82, 0xfe, 0x80, 0x00}, //0x6c l
{0xf8, 0x08, 0x70, 0x08, 0xf0}, //0x6d m
{0xf8, 0x10, 0x08, 0x08, 0xf0}, //0x6e n
{0x70, 0x88, 0x88, 0x88, 0x70}, //0x6f o
{0xf8, 0x48, 0x48, 0x48, 0x30}, //0x70 p
{0x30, 0x48, 0x48, 0x48, 0xf8}, //0x71 q
{0x00, 0xf8, 0x10, 0x08, 0x10}, //0x72 r
{0x90, 0xa8, 0xa8, 0xa8, 0x48}, //0x73 s
{0x08, 0x7e, 0x88, 0x80, 0x40}, //0x74 t
{0x78, 0x80, 0x80, 0x40, 0xf8}, //0x75 u
{0x38, 0x40, 0x80, 0x40, 0x38}, //0x76 v
{0x78, 0x80, 0x60, 0x80, 0x78}, //0x77 w
{0x88, 0x50, 0x20, 0x50, 0x88}, //0x78 x
{0x98, 0xa0, 0xa0, 0xa0, 0x78}, //0x79 y
{0x88, 0xc8, 0xa8, 0x98, 0x88}, //0x7a z
{0x00, 0x10, 0x6c, 0x82, 0x00}, //0x7b {
{0x00, 0x00, 0xfe, 0x00, 0x00}, //0x7c |
{0x00, 0x82, 0x6c, 0x10, 0x00}, //0x7d }
{0x04, 0x02, 0x04, 0x08, 0x04} //0x7e ~
};
// ============================================================================
// init
// ============================================================================
void st7565r_init()
{
// OED = 0xFF;
// ----------------------------------------------------
// initialization sequence
//
// note: - The circut must have a pulldown resistor
// for the RST line, because the controller
// pins in HiZ state on startup.
// ----------------------------------------------------
lcd_7565r_init();
st7565r_cmd_lcdbias(0); // LCD bias
st7565r_cmd_adcsel(1); // ADC
st7565r_cmd_coms(0); // Common Ouput Mode
// st7565r_cmd_v0reg( 0x03); // v0reg = 4.5 (0x03)
lcd_7565r_send( 0x25, 0);
// st7565r_cmd_evol( 0x12); // evol = 31 (0x1F)
st7565r_cmd_evol( 0x1F); // 38
st7565r_cmd_power(0x07); //
st7565r_cmd_boost(0x00); // boost = 3x,4x
lcd_7565r_send( 0x40, 0);
// lcd_7565r_send( 0xa7, 0); // inverse
// lcd_7565r_send( 0xac, 0);
// lcd_7565r_send( 0x00, 0);
lcd_7565r_send( 0xaf, 0);
st7565r_cls();
// st7565r_gotoxy(0,0); st7565r_puts("ABCDEFGHIJKLMNOPQRSTUV",22);
// st7565r_gotoxy(0,1); st7565r_puts("abcdefghijklmnopqrstuv",22);
// st7565r_gotoxy(0,2); st7565r_puts("0123456789WXYZwxyz()[]",22);
// st7565r_gotoxy(0,3); st7565r_puts("{}!\"#$\%&'*/+-._~^`<=>?",22);
// ----------------------------------------------------
// deactivate
// ----------------------------------------------------
lcd_7565r_deactivate();
}
// ============================================================================
// Display Normal/Reverse (means: inverse)
// ============================================================================
void st7565r_cmd_reverse( BYTE rev)
{
rev &= 0x01;
lcd_7565r_send( 0xA6 | rev, 0);
}
// ============================================================================
// Display All Points ON/OFF
// ============================================================================
void st7565r_cmd_dispall( BYTE disp)
{
disp &= 0x01;
lcd_7565r_send( 0xA4 | disp, 0);
}
// ============================================================================
// LCD Bias Set
// ============================================================================
void st7565r_cmd_lcdbias( BYTE bias)
{
bias &= 0x01;
lcd_7565r_send( 0xA2 | bias, 0);
}
// ============================================================================
// ADC select (means: right to left)
// ============================================================================
void st7565r_cmd_adcsel( BYTE sel)
{
sel &= 0x01;
lcd_7565r_send( 0xA0 | sel, 0);
}
// ============================================================================
// Common Output Mode Select
// ============================================================================
void st7565r_cmd_coms( BYTE coms)
{
coms = (coms & 0x01) << 3;
lcd_7565r_send( 0xC0 | coms, 0);
}
// ============================================================================
// V0 Voltage Regulator Internal Resistor Ratio Set (1+Rb/Ra)
//
// 0 0 0 - 3.0
// 0 0 1 - 3.5
// 0 1 0 - 4.0
// 0 1 1 - 4.5
// 1 0 0 - 5.0
// 1 0 1 - 5.5
// 1 1 0 - 6.0
// 1 1 1 - 6.5
// ============================================================================
void st7565r_cmd_v0reg( BYTE reg)
{
reg &= 0x07;
lcd_7565r_send( 0x20 | reg, 0);
}
// ============================================================================
// Electronic Volume Mode Set
// ============================================================================
void st7565r_cmd_evol( BYTE vol)
{
vol &= 0x3F;
lcd_7565r_send( 0x81, 0);
lcd_7565r_send( vol, 0);
}
// ============================================================================
// The Booster Ratio
//
// 0 0 - 2x,3x,4x
// 0 1 - 5x
// 1 1 - 6x
// ============================================================================
void st7565r_cmd_boost( BYTE boost)
{
boost &= 0x03;
lcd_7565r_send( 0xF8, 0);
lcd_7565r_send( boost,0);
}
// ============================================================================
// Power Constrol Set
//
// x x 1 - Voltage Follower On/Off
// x 1 x - Voltage Regulator On/Off
// 1 x x - Bosster Circuit On/Off
// ============================================================================
void st7565r_cmd_power( BYTE power)
{
power &= 0x07;
lcd_7565r_send( 0x28 | power, 0);
}
// ============================================================================
// Clear Screen
// ============================================================================
void st7565r_cls()
{
BYTE i;
BYTE j;
for( i=0; i<8; i++)
{
st7565r_gotoxy(0,i); // select page
for( j=0; j< 0x84; j++) // clear line
lcd_7565r_send( 0x00, 1);
}
st7565r_gotoxy(0,0);
}
void st7565r_putc( char c)
{
int i;
c -= 32;
for(i=0;i<5;i++)
lcd_7565r_send( ascii[c][i],1);
lcd_7565r_send( 0x00, 1);
}
void st7565r_puts( char *s, BYTE len)
{
BYTE i;
for(i=0;i<len;i++)
st7565r_putc(s[i]);
}
// ============================================================================
// Put 1 hexadecimal digit
// ============================================================================
void st7565r_putx1( BYTE x)
{
BYTE i;
x &= 0x0F;
for(i=0;i<5;i++)
lcd_7565r_send( ascii[x][i],1);
lcd_7565r_send( 0x00, 1);
}
// ============================================================================
// Put 2 hexadecimal digits
// ============================================================================
void st7565r_putx2( BYTE x)
{
BYTE i;
BYTE x1 = bin2hex[(x >> 4) & 0x0F];
BYTE x2 = bin2hex[(x >> 0) & 0x0F];
for(i=0;i<5;i++) lcd_7565r_send( ascii[x1][i],1); lcd_7565r_send( 0x00, 1);
for(i=0;i<5;i++) lcd_7565r_send( ascii[x2][i],1); lcd_7565r_send( 0x00, 1);
}
void st7565r_gotoxy( BYTE x, BYTE y)
{
BYTE hi;
BYTE lo;
if( (x < 22) && (y < 8))
{
x = x * 6;
hi = x >> 4;
lo = x & 0x0F;
lcd_7565r_send( 0xB0 | y, 0); // set page address (line)
lcd_7565r_send( 0x10 | hi, 0); // set column address to 0
lcd_7565r_send( 0x00 | lo, 0);
}
}
// ============================================================================
// Put raw graphic data
// ============================================================================
void st7565r_putg( BYTE *g, BYTE len)
{
BYTE i;
for(i=0; i<len; i++)
lcd_7565r_send(g[i],1);
}
// ============================================================================
// Put decimal number
// ============================================================================
void st7565r_putd( WORD d, BYTE l, bool showzero)
{
BYTE i;
BYTE d0 = 0; BYTE x0 = 0;
BYTE d1 = 0; BYTE x1 = 0;
BYTE d2 = 0; BYTE x2 = 0;
BYTE d3 = 0; BYTE x3 = 0;
BYTE d4 = 0; BYTE x4 = 0;
BYTE d5 = 0; BYTE x5 = 0;
BYTE d6 = 0; BYTE x6 = 0;
BYTE d7 = 0; BYTE x7 = 0;
d0 = d / 10000000; d = d % 10000000; x0 = bin2hex[d0];
d1 = d / 1000000; d = d % 1000000; x1 = bin2hex[d1];
d2 = d / 100000; d = d % 100000; x2 = bin2hex[d2];
d3 = d / 10000; d = d % 10000; x3 = bin2hex[d3];
d4 = d / 1000; d = d % 1000; x4 = bin2hex[d4];
d5 = d / 100; d = d % 100; x5 = bin2hex[d5];
d6 = d / 10; x6 = bin2hex[d6];
d7 = d % 10; x7 = bin2hex[d7];
if( false == showzero)
{
if( 0 == d4)
x4 = 0;
if( (0 == d4) && ( 0 == d5))
x5 = 0;
if( (0 == d4) && ( 0 == d5) && ( 0 == d6))
x6 = 0;
}
if(l>7) { for(i=0;i<5;i++) lcd_7565r_send( ascii[x0][i],1); lcd_7565r_send( 0x00, 1); }
if(l>6) { for(i=0;i<5;i++) lcd_7565r_send( ascii[x1][i],1); lcd_7565r_send( 0x00, 1); }
if(l>5) { for(i=0;i<5;i++) lcd_7565r_send( ascii[x2][i],1); lcd_7565r_send( 0x00, 1); }
if(l>4) { for(i=0;i<5;i++) lcd_7565r_send( ascii[x3][i],1); lcd_7565r_send( 0x00, 1); }
if(l>3) { for(i=0;i<5;i++) lcd_7565r_send( ascii[x4][i],1); lcd_7565r_send( 0x00, 1); }
if(l>2) { for(i=0;i<5;i++) lcd_7565r_send( ascii[x5][i],1); lcd_7565r_send( 0x00, 1); }
if(l>1) { for(i=0;i<5;i++) lcd_7565r_send( ascii[x6][i],1); lcd_7565r_send( 0x00, 1); }
if(l>0) { for(i=0;i<5;i++) lcd_7565r_send( ascii[x7][i],1); lcd_7565r_send( 0x00, 1); }
}