📄 sed1520.c
字号:
/**************************************************************************
*
* sed1520.c
* LCD display controller interface routines for graphics modules
* with onboard SED1520 controller(s) in "write-only" setup
*
* Version 1.02 (20051031)
*
* For Atmel AVR controllers with avr-gcc/avr-libc
* Copyright (c) 2005
* Martin Thomas, Kaiserslautern, Germany
* <eversmith@heizung-thomas.de>
* http://www.siwawi.arubi.uni-kl.de/avr_projects
*
* Permission to use in NON-COMMERCIAL projects is herbey granted. For
* a commercial license contact the author.
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*
* partly based on code published by:
* Michael J. Karas and Fabian "ape" Thiele
*
*
***************************************************************************/
/*
An Emerging Display EW12A03LY 122x32 Graphics module has been used
for testing. This module only supports "write". There is no option
to read data from the SED1520 RAM. The SED1520 R/W line on the
module is bound to GND according to the datasheet. Because of this
Read-Modify-Write using the LCD-RAM is not possible with the 12A03
LCD-Module. So this library uses a "framebuffer" which needs
ca. 500 bytes of the AVR's SRAM. The libray can of cause be used
with read/write modules too.
*/
/* tab-width: 4 */
#include <avr/io.h>
#include <avr/delay.h>
#include <stdint.h>
#include "sed1520.h"
#include "fonts.h"
#include "bmp.h"
/* pixel level bit masks for display */
/* this array is setup to map the order */
/* of bits in a byte to the vertical order */
/* of bits at the LCD controller */
const unsigned char l_mask_array[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; /* TODO: avoid or PROGMEM */
/* the LCD display image memory */
/* buffer arranged so page memory is sequential in RAM */
unsigned char l_display_array[LCD_Y_BYTES][LCD_X_BYTES];
/* control-lines hardware-interface (only "write") */
#define LCD_CMD_MODE() LCDCTRLPORT &= ~(1<<LCDCMDPIN)
#define LCD_DATA_MODE() LCDCTRLPORT |= (1<<LCDCMDPIN)
#define LCD_ENABLE_E1() LCDCTRLPORT &= ~(1<<LCDE1PIN)
#define LCD_DISABLE_E1() LCDCTRLPORT |= (1<<LCDE1PIN)
#define LCD_ENABLE_E2() LCDCTRLPORT &= ~(1<<LCDE2PIN)
#define LCD_DISABLE_E2() LCDCTRLPORT |= (1<<LCDE2PIN)
/*
**
** Low level LCD Controller Interface Support Routines
**
*/
static void lcd_strobe_delay(void)
{ //
#ifndef LCD_SIM
_delay_us(1);
#endif
}
static void lcd_long_delay(void)
{
#ifndef LCD_SIM
_delay_ms(100);
#endif
}
static void lcd_strobe_e(const unsigned char ncontr)
{ lcd_strobe_delay();
if ( ncontr & 0x01 )
LCD_ENABLE_E1();
if ( ncontr & 0x02 )
LCD_ENABLE_E2();
lcd_strobe_delay();
LCD_DISABLE_E1();
LCD_DISABLE_E2();
}
/*
**
** low level routine to send a byte value
** to the LCD controller control register.
** entry argument is the data to output
** and the controller to use
** 1: IC 1, 2: IC 2, 3: both ICs
**
*/
void lcd_out_ctl(const unsigned char cmd, const unsigned char ncontr)
{ LCD_CMD_MODE();
LCDDATAPORT = cmd;
lcd_strobe_e(ncontr);
}
/*
**
** low level routine to send a byte value
** to the LCD controller data register. entry argument
** is the data to output and the controller-number
**
*/
void lcd_out_dat(const unsigned char dat, const unsigned char ncontr)
{ LCD_DATA_MODE();
LCDDATAPORT = dat;
lcd_strobe_e(ncontr);
}
/*
**
** routine to initialize the operation of the LCD display subsystem
**
*/
void lcd_init(void)
{ LCDDATADDR = 0xff; /* all output */
LCDCTRLDDR |= ( (1<<LCDCMDPIN) | (1<<LCDE1PIN) | (1<<LCDE2PIN) );
lcd_out_ctl(0,3);
lcd_out_ctl(LCD_RESET,3);
lcd_long_delay();
lcd_out_ctl(LCD_DISP_ON,3);
lcd_out_ctl(LCD_SET_ADC_REV,3); // !
lcd_out_ctl(LCD_SET_LINE+0,3);
lcd_out_ctl(LCD_SET_PAGE+0,3);
lcd_out_ctl(LCD_SET_COL+LCD_STARTCOL_REVERSE,3);
}
#ifdef LCD_DEBUG
/* fills complete area with pattern - direct to LCD-RAM */
void lcd_test(const unsigned char pattern)
{ unsigned char page, col;
for (page=0; page<LCD_Y_BYTES; page++)
{ lcd_out_ctl(LCD_SET_PAGE+page,3);
lcd_out_ctl(LCD_SET_COL+LCD_STARTCOL_REVERSE,3); // !
for (col=0; col<LCD_X_BYTES/2; col++)
lcd_out_dat(pattern,3);
}
}
/* raw write to LCD-RAM - used for debugging */
void lcd_raw(const unsigned char page, const unsigned char col, const unsigned char nctrl, const unsigned char pattern)
{ lcd_out_ctl(LCD_SET_PAGE+page,nctrl);
lcd_out_ctl(LCD_SET_COL+col,nctrl);
lcd_out_dat(pattern,nctrl);
}
#endif /* LCD_DEBUG */
/* fill buffer and LCD with pattern */
void lcd_fill(const unsigned char pattern)
{ unsigned char page, col;
for (page=0; page<LCD_Y_BYTES; page++)
{ for (col=0; col<LCD_X_BYTES; col++)
l_display_array[page][col]=pattern;
}
lcd_update_all();
}
void lcd_erase(void)
{ lcd_fill(0x00);
lcd_update_all();
}
/*
**
** Updates area of the display. Writes data from "framebuffer"
** RAM to the lcd display controller RAM.
**
** Arguments Used:
** top top line of area to update.
** bottom bottom line of area to update.
** from MJK-Code
**
*/
void lcd_update(const unsigned char top, const unsigned char bottom)
{ unsigned char x;
unsigned char y;
unsigned char yt;
unsigned char yb;
unsigned char *colptr;
/* setup bytes of range */
yb = bottom >> 3;
yt = top >> 3;
for(y = yt; y <= yb; y++)
{ lcd_out_ctl(LCD_SET_PAGE+y,3); /* set page */
// lcd_out_ctl(LCD_SET_COL+LCD_STARTCOL_REVERSE,3);
lcd_out_ctl(LCD_SET_COL+0,3);
colptr = &l_display_array[y][0];
for (x=0; x < LCD_X_BYTES; x++)
{ if ( x < LCD_X_BYTES/2 )
lcd_out_dat(*colptr++,1);
else
lcd_out_dat(*colptr++,2);
}
}
}
void lcd_update_all(void)
{ lcd_update(SCRN_TOP,SCRN_BOTTOM);
}
/* sets/clears/switchs(XOR) dot at (x,y) */
void lcd_dot(const unsigned char x, const unsigned char y, const unsigned char mode)
{ unsigned char bitnum, bitmask, yByte;
unsigned char *pBuffer; /* pointer used for optimisation */
if ( ( x > SCRN_RIGHT ) || ( y > SCRN_BOTTOM ) ) return;
yByte = y >> 3;
bitnum = y & 0x07;
bitmask = l_mask_array[bitnum]; // bitmask = ( 1 << (y & 0x07) );
pBuffer = &(l_display_array[yByte][x]);
switch (mode)
{ case LCD_MODE_SET:
*pBuffer |= bitmask;
break;
case LCD_MODE_CLEAR:
*pBuffer &= ~bitmask;
break;
case LCD_MODE_XOR:
*pBuffer ^= bitmask;
break;
default: break;
}
}
/* line- and circle-function from a KS0108-library by F. Thiele */
void lcd_line( uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, const uint8_t mode )
{ uint8_t length, xTmp, yTmp, i, y, yAlt;
int16_t m;
if(x1 == x2)
{ // vertical line
// x1|y1 must be the upper point
if(y1 > y2)
{ xTmp = x1;
yTmp = y1;
x1 = x2;
y1 = y2;
x2 = xTmp;
y2 = yTmp;
}
length = y2-y1;
for(i=0; i<=length; i++)
lcd_dot(x1, y1+i, mode);
}
else if(y1 == y2)
{ // horizontal line
// x1|y1 must be the left point
if(x1 > x2)
{ xTmp = x1;
yTmp = y1;
x1 = x2;
y1 = y2;
x2 = xTmp;
y2 = yTmp;
}
length = x2-x1;
for(i=0; i<=length; i++)
lcd_dot(x1+i, y1, mode);
}
else
{ // x1 must be smaller than x2
if(x1 > x2)
{ xTmp = x1;
yTmp = y1;
x1 = x2;
y1 = y2;
x2 = xTmp;
y2 = yTmp;
}
if((y2-y1) >= (x2-x1) || (y1-y2) >= (x2-x1))
{ // angle larger or equal 45
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -