2 Commits b946c3ac51 ... 127dd9d74b

Tác giả SHA1 Thông báo Ngày
  k4be 127dd9d74b Graphical LCD is usable (not fully utilized) 1 năm trước cách đây
  kbere ccd1000e23 Start working with graphical LCD 1 năm trước cách đây
8 tập tin đã thay đổi với 427 bổ sung6 xóa
  1. 23 0
      README.md
  2. 10 1
      soft/Makefile
  3. 219 0
      soft/UC1601S-I2C.c
  4. 149 0
      soft/UC1601S-I2C.h
  5. 13 3
      soft/display.c
  6. 5 1
      soft/main.c
  7. 8 0
      soft/main.h
  8. 0 1
      soft/working_modes.c

+ 23 - 0
README.md

@@ -0,0 +1,23 @@
+Software build & programming:
+
+First, install bootloader using USBASP:
+```
+cd optiboot
+make install
+```
+
+Second, program the main software.
+
+Alphanumeric display version:
+```
+cd soft
+make install PROGPORT=COM16 LCD=alnum
+```
+
+Graphical display version:
+```
+cd soft
+make install PROGPORT=COM16 LCD=graphic
+```
+
+Warning: remember to ```make clean``` when switching between versions.

+ 10 - 1
soft/Makefile

@@ -2,7 +2,7 @@
 PROJECT	= glg
 
 ### Source files and search directory
-CSRC    = main.c uart0.c uart1.c ff.c mmc.c 1wire.c ds18b20.c expander.c HD44780-I2C.c I2C.c xprintf.c gpx.c ffunicode.c display.c working_modes.o timec.o nmea.o settings.o menu.o
+CSRC    = main.c uart0.c uart1.c ff.c mmc.c 1wire.c ds18b20.c expander.c I2C.c xprintf.c gpx.c ffunicode.c display.c working_modes.o timec.o nmea.o settings.o menu.o
 ASRC    = stime.S
 VPATH   =
 
@@ -26,6 +26,15 @@ DEFS	= F_CPU=7372800
 # DEFS	+= LEDR_UART
 ADEFS	=
 
+ifeq ($(LCD),graphic)
+CSRC	+= UC1601S-I2C.c
+DEFS	+= LCD_GRAPHIC
+endif
+ifeq ($(LCD),alnum)
+CSRC	+= HD44780-I2C.c
+DEFS	+= LCD_ALNUM
+endif
+
 ### Warning contorls
 WARNINGS = all extra
 

+ 219 - 0
soft/UC1601S-I2C.c

@@ -0,0 +1,219 @@
+#include "UC1601S-I2C.h"
+#include <avr/pgmspace.h>
+
+__flash const unsigned char FontLookup [][5] = {
+	{ 0x00, 0x00, 0x00, 0x00, 0x00 },  // sp
+	{ 0x00, 0x00, 0x2f, 0x00, 0x00 },   // !
+	{ 0x00, 0x07, 0x00, 0x07, 0x00 },   // "
+	{ 0x14, 0x7f, 0x14, 0x7f, 0x14 },   // #
+	{ 0x24, 0x2a, 0x7f, 0x2a, 0x12 },   // $
+	{ 0xc4, 0xc8, 0x10, 0x26, 0x46 },   // %
+	{ 0x36, 0x49, 0x55, 0x22, 0x50 },   // &
+	{ 0x00, 0x05, 0x03, 0x00, 0x00 },   // '
+	{ 0x00, 0x1c, 0x22, 0x41, 0x00 },   // (
+	{ 0x00, 0x41, 0x22, 0x1c, 0x00 },   // )
+	{ 0x14, 0x08, 0x3E, 0x08, 0x14 },   // *
+	{ 0x08, 0x08, 0x3E, 0x08, 0x08 },   // +
+	{ 0x00, 0x00, 0x50, 0x30, 0x00 },   // ,
+	{ 0x10, 0x10, 0x10, 0x10, 0x10 },   // -
+	{ 0x00, 0x60, 0x60, 0x00, 0x00 },   // .
+	{ 0x20, 0x10, 0x08, 0x04, 0x02 },   // /
+	{ 0x3E, 0x51, 0x49, 0x45, 0x3E },   // 0
+	{ 0x00, 0x42, 0x7F, 0x40, 0x00 },   // 1
+	{ 0x42, 0x61, 0x51, 0x49, 0x46 },   // 2
+	{ 0x21, 0x41, 0x45, 0x4B, 0x31 },   // 3
+	{ 0x18, 0x14, 0x12, 0x7F, 0x10 },   // 4
+	{ 0x27, 0x45, 0x45, 0x45, 0x39 },   // 5
+	{ 0x3C, 0x4A, 0x49, 0x49, 0x30 },   // 6
+	{ 0x01, 0x71, 0x09, 0x05, 0x03 },   // 7
+	{ 0x36, 0x49, 0x49, 0x49, 0x36 },   // 8
+	{ 0x06, 0x49, 0x49, 0x29, 0x1E },   // 9
+	{ 0x00, 0x36, 0x36, 0x00, 0x00 },   // :
+	{ 0x00, 0x56, 0x36, 0x00, 0x00 },   // ;
+	{ 0x08, 0x14, 0x22, 0x41, 0x00 },   // <
+	{ 0x14, 0x14, 0x14, 0x14, 0x14 },   // =
+	{ 0x00, 0x41, 0x22, 0x14, 0x08 },   // >
+	{ 0x02, 0x01, 0x51, 0x09, 0x06 },   // ?
+	{ 0x32, 0x49, 0x59, 0x51, 0x3E },   // @
+	{ 0x7E, 0x11, 0x11, 0x11, 0x7E },   // A
+	{ 0x7F, 0x49, 0x49, 0x49, 0x36 },   // B
+	{ 0x3E, 0x41, 0x41, 0x41, 0x22 },   // C
+	{ 0x7F, 0x41, 0x41, 0x22, 0x1C },   // D
+	{ 0x7F, 0x49, 0x49, 0x49, 0x41 },   // E
+	{ 0x7F, 0x09, 0x09, 0x09, 0x01 },   // F
+	{ 0x3E, 0x41, 0x49, 0x49, 0x7A },   // G
+	{ 0x7F, 0x08, 0x08, 0x08, 0x7F },   // H
+	{ 0x00, 0x41, 0x7F, 0x41, 0x00 },   // I
+	{ 0x20, 0x40, 0x41, 0x3F, 0x01 },   // J
+	{ 0x7F, 0x08, 0x14, 0x22, 0x41 },   // K
+	{ 0x7F, 0x40, 0x40, 0x40, 0x40 },   // L
+	{ 0x7F, 0x02, 0x0C, 0x02, 0x7F },   // M
+	{ 0x7F, 0x04, 0x08, 0x10, 0x7F },   // N
+	{ 0x3E, 0x41, 0x41, 0x41, 0x3E },   // O
+	{ 0x7F, 0x09, 0x09, 0x09, 0x06 },   // P
+	{ 0x3E, 0x41, 0x51, 0x21, 0x5E },   // Q
+	{ 0x7F, 0x09, 0x19, 0x29, 0x46 },   // R
+	{ 0x46, 0x49, 0x49, 0x49, 0x31 },   // S
+	{ 0x01, 0x01, 0x7F, 0x01, 0x01 },   // T
+	{ 0x3F, 0x40, 0x40, 0x40, 0x3F },   // U
+	{ 0x1F, 0x20, 0x40, 0x20, 0x1F },   // V
+	{ 0x3F, 0x40, 0x38, 0x40, 0x3F },   // W
+	{ 0x63, 0x14, 0x08, 0x14, 0x63 },   // X
+	{ 0x07, 0x08, 0x70, 0x08, 0x07 },   // Y
+	{ 0x61, 0x51, 0x49, 0x45, 0x43 },   // Z
+	{ 0x00, 0x7F, 0x41, 0x41, 0x00 },   // [
+	{ 0x55, 0x2A, 0x55, 0x2A, 0x55 },   // 55
+	{ 0x00, 0x41, 0x41, 0x7F, 0x00 },   // ]
+	{ 0x04, 0x02, 0x01, 0x02, 0x04 },   // ^
+	{ 0x40, 0x40, 0x40, 0x40, 0x40 },   // _
+	{ 0x00, 0x01, 0x02, 0x04, 0x00 },   // '
+	{ 0x20, 0x54, 0x54, 0x54, 0x78 },   // a
+	{ 0x7F, 0x48, 0x44, 0x44, 0x38 },   // b
+	{ 0x38, 0x44, 0x44, 0x44, 0x28 },   // c
+	{ 0x38, 0x44, 0x44, 0x48, 0x7F },   // d
+	{ 0x38, 0x54, 0x54, 0x54, 0x18 },   // e
+	{ 0x08, 0x7E, 0x09, 0x01, 0x02 },   // f
+	{ 0x0C, 0x52, 0x52, 0x52, 0x3E },   // g
+	{ 0x7F, 0x08, 0x04, 0x04, 0x78 },   // h
+	{ 0x00, 0x44, 0x7D, 0x40, 0x00 },   // i
+	{ 0x20, 0x40, 0x44, 0x3D, 0x00 },   // j
+	{ 0x7F, 0x10, 0x28, 0x44, 0x00 },   // k
+	{ 0x00, 0x41, 0x7F, 0x40, 0x00 },   // l
+	{ 0x7C, 0x04, 0x18, 0x04, 0x78 },   // m
+	{ 0x7C, 0x08, 0x04, 0x04, 0x78 },   // n
+	{ 0x38, 0x44, 0x44, 0x44, 0x38 },   // o
+	{ 0x7C, 0x14, 0x14, 0x14, 0x08 },   // p
+	{ 0x08, 0x14, 0x14, 0x18, 0x7C },   // q
+	{ 0x7C, 0x08, 0x04, 0x04, 0x08 },   // r
+	{ 0x48, 0x54, 0x54, 0x54, 0x20 },   // s
+	{ 0x04, 0x3F, 0x44, 0x40, 0x20 },   // t
+	{ 0x3C, 0x40, 0x40, 0x20, 0x7C },   // u
+	{ 0x1C, 0x20, 0x40, 0x20, 0x1C },   // v
+	{ 0x3C, 0x40, 0x30, 0x40, 0x3C },   // w
+	{ 0x44, 0x28, 0x10, 0x28, 0x44 },   // x
+	{ 0x0C, 0x50, 0x50, 0x50, 0x3C },   // y
+	{ 0x44, 0x64, 0x54, 0x4C, 0x44 },   // z
+	{ 0x7F, 0x50, 0x48, 0x44, 0x40 },   // Ł \x7b
+	{ 0x44, 0x64, 0x56, 0x4D, 0x44 },   // ź \x7c
+	{ 0x38, 0x54, 0xd4, 0x54, 0x18 },   // ę \x7d
+	{ 0x48, 0x54, 0x56, 0x55, 0x20 },   // ś \x7e
+	{ 0x20, 0x54, 0x54, 0xd4, 0x78 },   // ą \x7f
+	{ 0x38, 0x44, 0x46, 0x45, 0x28 },   // ć \x80
+	{ 0x00, 0x49, 0x7F, 0x44, 0x00 },   // ł \x81
+	{ 0xfe, 0x43, 0x43, 0x43, 0xfe },	// 0/3 \x82
+	{ 0xfe, 0xe3, 0xe3, 0xe3, 0xfe },	// 1/3 \x83
+	{ 0xfe, 0xfb, 0xfb, 0xfb, 0xfe },	// 2/3 \x84
+	{ 0xfe, 0xff, 0xff, 0xff, 0xfe },	// 3/3 \x85
+};
+/*
+__flash const unsigned char custom_chars[] = {
+	0b00000, /* 0x01 down arrow *//*
+	0b00100,
+	0b00100,
+	0b00100,
+	0b10101,
+	0b01110,
+	0b00100,
+	0b00000,
+	
+	0b00000, /* 0x02 up arrow *//*
+	0b00100,
+	0b01110,
+	0b10101,
+	0b00100,
+	0b00100,
+	0b00100,
+	0b00000,
+};*/
+
+void uc1601s_write_command(unsigned char cmd) {
+	expander_set_bit_no_send(UC1601S_CD_PORT, UC1601S_CD, 0);
+	exp_output[0] = cmd;
+	expander_write(0);
+	expander_set_bit(UC1601S_WR_PORT, UC1601S_WR, 0);
+	expander_set_bit_no_send(UC1601S_WR_PORT, UC1601S_WR, 1);
+	expander_set_bit(UC1601S_CD_PORT, UC1601S_CD, 1);
+}
+
+void uc1601s_write_data(unsigned char data) {
+	exp_output[0] = data;
+	expander_write(0);
+	expander_set_bit(UC1601S_WR_PORT, UC1601S_WR, 0);
+	expander_set_bit(UC1601S_WR_PORT, UC1601S_WR, 1);
+}
+
+unsigned char uc1601s_read_data(void) {
+	unsigned char out;
+	UC1601S_DATA_INPUT();
+	expander_set_bit(UC1601S_RD_PORT, UC1601S_RD, 0);
+	out = expander_read_byte(0, 0);
+	expander_set_bit(UC1601S_RD_PORT, UC1601S_RD, 1);
+	UC1601S_DATA_OUTPUT();
+	return out;
+}
+
+#define LCD_COM_COUNT	32
+#define LCD_ROW_COUNT	(LCD_COM_COUNT/8)
+#define LCD_COL_COUNT	128
+
+#define UC1601S_MY		0x4
+#define UC1601S_MX		0x2
+
+void LCD_Initialize(void) {
+	expander_set_bit_no_send(UC1601S_CS_PORT, UC1601S_CS, 0);
+	expander_set_bit(UC1601S_RST_PORT, UC1601S_RST, 1);
+	_delay_ms(5);
+	expander_set_bit_no_send(UC1601S_RD_PORT, UC1601S_RD, 1);
+	expander_set_bit(UC1601S_WR_PORT, UC1601S_WR, 1);
+	UC1601S_DATA_OUTPUT();
+	uc1601s_set_power_control(UC1601S_INTERNAL_VLCD);
+	uc1601s_set_lcd_bias_ratio(UC1601S_BIAS_RATIO_7);
+	uc1601s_set_com_end(LCD_COM_COUNT-1);
+	uc1601s_set_lcd_mapping(UC1601S_MY);
+	uc1601s_set_vbias(230);
+	uc1601s_set_display_enable(1);
+}
+
+void LCD_Clear(void) {
+	unsigned int col, row;
+	
+	for (row=0; row<LCD_ROW_COUNT; row++) {
+		uc1601s_set_page_address(row);
+		uc1601s_set_column_address(0);
+		for (col=0; col<LCD_COL_COUNT; col++) {
+			uc1601s_write_data(0);
+		}
+	}
+}
+
+void LCD_GoTo(unsigned char x, unsigned char y) {
+	uc1601s_set_page_address(y);
+	uc1601s_set_column_address(x*6);
+}
+
+
+void LCD_WriteTextP(__flash const char *t) {
+	char c;
+	while ((c = pgm_read_byte(t))) {
+		LCD_WriteChar(c);
+		t++;
+	}
+}
+
+void LCD_WriteText(const char *t) {
+	while (*t) {
+		LCD_WriteChar(*t);
+		t++;
+	}
+}
+
+void LCD_WriteChar(char c) {
+	unsigned char col;
+	
+	c -= ' ';
+	for (col = 0; col < 5; col++) {
+		uc1601s_write_data(FontLookup[(int)c][col]);
+	}
+	uc1601s_write_data(0);
+}
+

+ 149 - 0
soft/UC1601S-I2C.h

@@ -0,0 +1,149 @@
+#pragma once
+
+#include <avr/io.h>
+#include <util/delay.h>
+#include "expander.h"
+
+#define LCD_WriteCommand(x)
+
+#define UC1601S_CA30	0x00
+#define UC1601S_CA74	0x10
+#define UC1601S_TC	0x24
+#define UC1601S_PC	0x28
+#define UC1601S_ADV	0x30
+#define UC1601S_SL	0x40
+#define UC1601S_PA	0xb0
+#define UC1601S_PM	0x81
+#define UC1601S_LC4	0x84
+#define UC1601S_AC	0x88
+#define UC1601S_LC3	0xa0
+#define UC1601S_DC1	0xa4
+#define UC1601S_DC0	0xa6
+#define UC1601S_DC2	0xae
+#define UC1601S_LC21	0xc0
+#define UC1601S_SYSTEMRESET	0xe2
+#define UC1601S_NOP	0xe3
+#define UC1601S_BR	0xe8
+#define UC1601S_CEN	0xf1
+#define UC1601S_DST	0xf2
+#define UC1601S_DEN	0xf3
+
+#define UC1601S_INTERNAL_VLCD	0x6
+#define UC1601S_BIAS_RATIO_6	0x0
+#define UC1601S_BIAS_RATIO_7	0x1
+#define UC1601S_BIAS_RATIO_8	0x2
+#define UC1601S_BIAS_RATIO_9	0x3
+
+#define UC1601S_DATA_OUTPUT() 	expander_set_dir(0, 0x00, 0x00)
+#define UC1601S_DATA_INPUT() 	expander_set_dir(0, 0xFF, 0x00)
+
+#define UC1601S_WR_PORT	1
+#define UC1601S_WR		(1<<2)
+#define UC1601S_CD_PORT	1
+#define UC1601S_CD		(1<<0)
+#define UC1601S_RD_PORT	1
+#define UC1601S_RD		(1<<3)
+#define UC1601S_CS_PORT	1
+#define UC1601S_CS		(1<<1)
+#define UC1601S_RST_PORT	1
+#define UC1601S_RST		(1<<6)
+
+void uc1601s_write_command(unsigned char cmd);
+void uc1601s_write_data(unsigned char data);
+unsigned char uc1601s_read_data(void);
+void LCD_Initialize(void);
+void LCD_Clear(void);
+void LCD_GoTo(unsigned char x, unsigned char y);
+void LCD_WriteTextP(__flash const char *t);
+void LCD_WriteText(const char *t);
+void LCD_WriteChar(char c);
+#define LCD_WriteData(c) LCD_WriteChar(c)
+
+static inline void uc1601s_set_column_address(unsigned char addr) {
+	uc1601s_write_command(UC1601S_CA30 | (addr&0x0f));
+	uc1601s_write_command(UC1601S_CA74 | (addr>>4));
+}
+
+static inline void uc1601s_set_temp_compensation(unsigned char tc) {
+	tc &= 0x3;
+	uc1601s_write_command(UC1601S_TC | tc);
+}
+
+static inline void uc1601s_set_power_control(unsigned char pc) {
+	pc &= 0x7;
+	uc1601s_write_command(UC1601S_PC | pc);
+}
+
+static inline void uc1601s_set_scroll_line(unsigned char sl) {
+	sl &= 0x3f;
+	uc1601s_write_command(UC1601S_SL | sl);
+}
+
+static inline void uc1601s_set_page_address(unsigned char pa) {
+	pa &= 0x0f;
+	uc1601s_write_command(UC1601S_PA | pa);
+}
+
+static inline void uc1601s_set_vbias(unsigned char pm) {
+	uc1601s_write_command(UC1601S_PM);
+	uc1601s_write_command(pm);
+}
+
+static inline void uc1601s_set_partial_display(unsigned char lc) {
+	lc &= 0x1;
+	uc1601s_write_command(UC1601S_LC4 | lc);
+}
+
+static inline void uc1601s_set_ram_address(unsigned char ac) {
+	ac &= 0x3;
+	uc1601s_write_command(UC1601S_AC | ac);
+}
+
+static inline void uc1601_set_frame_rate(unsigned char lc) {
+	lc &= 0x1;
+	uc1601s_write_command(UC1601S_LC3 | lc);
+}
+
+static inline void uc1601s_set_all_pixel_on(unsigned char dc) {
+	dc &= 0x1;
+	uc1601s_write_command(UC1601S_DC1 | dc);
+}
+
+static inline void uc1601s_set_inverse_display(unsigned char dc) {
+	dc &= 0x1;
+	uc1601s_write_command(UC1601S_DC0 | dc);
+}
+
+static inline void uc1601s_set_display_enable(unsigned char dc) {
+	dc &= 0x1;
+	uc1601s_write_command(UC1601S_DC2 | dc);
+}
+
+static inline void uc1601s_set_lcd_mapping(unsigned char lc) {
+	lc &= 0x6;
+	uc1601s_write_command(UC1601S_LC21 | lc);
+}
+
+static inline void uc1601s_system_reset(void) {
+	uc1601s_write_command(UC1601S_SYSTEMRESET);
+}
+
+static inline void uc1601s_set_lcd_bias_ratio(unsigned char br) {
+	br &= 0x3;
+	uc1601s_write_command(UC1601S_BR | br);
+}
+
+static inline void uc1601s_set_com_end(unsigned char cen) {
+	uc1601s_write_command(UC1601S_CEN);
+	uc1601s_write_command(cen);
+}
+
+static inline void uc1601s_set_partial_display_start(unsigned char dst) {
+	uc1601s_write_command(UC1601S_DST);
+	uc1601s_write_command(dst);
+}
+
+static inline void uc1601s_set_partial_display_end(unsigned char den) {
+	uc1601s_write_command(UC1601S_DEN);
+	uc1601s_write_command(den);
+}

+ 13 - 3
soft/display.c

@@ -1,11 +1,11 @@
 #include <avr/pgmspace.h>
 #include "main.h"
 #include "display.h"
-#include "HD44780-I2C.h"
 #include "xprintf.h"
 #include "working_modes.h"
 #include "timec.h"
 
+#ifndef LCD_GRAPHIC
 __flash const unsigned char battery_states[][8] = {
 	{
 		0b01110,
@@ -68,19 +68,21 @@ __flash const unsigned char custom_chars[] = {
 	0b00100,
 	0b00000,
 };
+#endif /* LCD_GRAPHIC */
 
 struct disp_s disp;
 
 void disp_init(void) { /* send custom characters starting with 0x01 */
+#ifndef LCD_GRAPHIC
 	unsigned char i;
 	LCD_WriteCommand(0x40 + 8); // 0x01
 	for(i=0; i<sizeof(custom_chars); i++){
 		LCD_WriteData(custom_chars[i]);
 	};
+#endif /* LCD_GRAPHIC */
 }
 
 void battery_state_display(void) {
-	unsigned char i;
 	unsigned char index;
 	if (System.bat_volt > 4.0)
 		index = 0;
@@ -90,12 +92,18 @@ void battery_state_display(void) {
 		index = 2;
 	else
 		index = 3;
-	
+
+#ifdef LCD_GRAPHIC
+	LCD_GoTo(15,0);
+	LCD_WriteChar(0x82 + index);
+#else
+	unsigned char i;
 	LCD_WriteCommand(0x40 + 0); // 0x00
 
 	for(i=0; i<8; i++){
 		LCD_WriteData(battery_states[index][i]);
 	};
+#endif /* LCD_GRAPHIC */
 }
 
 static inline void disp_line(unsigned char i, __flash const char *text) {
@@ -286,7 +294,9 @@ void display_refresh(unsigned char changed) {
 			len++;
 			LCD_WriteData(' ');
 		}
+#ifndef LCD_GRAPHIC
 		LCD_WriteData(0); /* battery symbol */
+#endif
 		LCD_GoTo(0,1);
 		len = strlen(disp.line2);
 		LCD_WriteText(disp.line2);

+ 5 - 1
soft/main.c

@@ -21,7 +21,6 @@
 #include "ds18b20.h"
 #include "I2C.h"
 #include "expander.h"
-#include "HD44780-I2C.h"
 #include "gpx.h"
 #include "display.h"
 #include "working_modes.h"
@@ -239,9 +238,14 @@ void ioinit (void)
 	
 	I2C_init();
 	expander_init(0, 0x00, 0x00); /* all as outputs */
+	
 	LCD_Initialize();
 	LCD_Clear();
 
+	LCD_GoTo(0,0);
+
+	wdt_reset();
+
 	sei();
 	
 	ADCSRA |= _BV(ADSC);

+ 8 - 0
soft/main.h

@@ -8,6 +8,14 @@
 #include "expander.h"
 #include "settings.h"
 
+#if defined(LCD_GRAPHIC)
+#include "UC1601S-I2C.h"
+#elif defined(LCD_ALNUM)
+#include "HD44780-I2C.h"
+#else
+#error No LCD type defined
+#endif
+
 #define	IVT_SYNC	180			/* f_sync() interval (0:no periodic sync) [sec] */
 #define POWER_SW_TIME	300		/* power switch hold time to power off [10ms] */
 #define BACKLIGHT_TIME	10000

+ 0 - 1
soft/working_modes.c

@@ -1,7 +1,6 @@
 #include "main.h"
 #include "working_modes.h"
 #include "display.h"
-#include "HD44780-I2C.h"
 #include "xprintf.h"
 #include "settings.h"
 #include "nmea.h"