oswald/metawatch/sharp_mem_lcd.c

114 lines
3.8 KiB
C
Raw Normal View History

2021-02-14 18:03:13 +01:00
// taken and adapted from
// Programming Sharps Memory LCDs
// by Ken Green
// LCD commands - Note: the bits are reversed per the memory LCD data
// sheets because of the order the bits are shifted out in the SPI
// port.
#define MLCD_WR 0x80 //MLCD write line command
#define MLCD_CM 0x20 //MLCD clear memory command
#define MLCD_NO 0x00 //MLCD NOP command (used to switch VCOM)
//LCD resolution
#define MLCD_XRES 96 //pixels per horizontal line
#define MLCD_YRES 96 //pixels per vertical line
#define MLCD_BYTES_LINE MLCD_XRES / 8 //number of bytes in a line
#define MLCD_BUF_SIZE MLCD_YRES * MLCD_BYTES_LINE
//defines the VCOM bit in the command word that goes to the LCD
#define VCOM_HI 0x40
#define VCOM_LO 0x00
static char *frmbufter; //current address of buffer to be displayed
static char locbuf[MLCD_BYTES_LINE + 3]; // local line buffer
static char linenum; // current line number being transmitted
//there are 3 stages in transmitting a buffer:
//stage 0: first line (has command in it)
//stage 1: 2nd through last line (no command)
//stage 2: null byte trailer
static int stage = 0;
//current state of vcom. This should alternate
//between VCOM _ HI and VCOM _ LO on a 1-30 second
//period.
extern char vcom;
////////////////////////////////////////////////////////////////
//
// This routine transmits the contents of the pixel memory in
// a frame buffer to the memory LCD. It uses DMA to transfer
// each individual line. The address of the frame buffer to
// transfer is in the global variable show _ frm.
//
//
// NOTE: this routine also acts as the interrupt handler for SPI interrupts.
//
//
// INPUTS:
// The SPI and DMA units must have been previously initialized
// show _ frm:
// pointer to the buffer to be displayed
//
////////////////////////////////////////////////////////////////
void show _ frame(char *show _ frm) {
int i;
unsigned long sts;
switch(stage) {
case 0:
// stage 0: sending the first line. The command is
// included in this line
set_scs(HIGH); //set SCS high
frmbufptr = show_frm; //init pointer to frame buffer
linebuf = locbuf; //init pointer to line buffer
linenum = 1; //init line address
//first line of data is preceeded by a write command
*linebuf++ = MLCD _ WR | vcom; //command (note: no need to swap)
*linebuf++ = swap(linenum++); //line number (address)
for (i=0; i<MLCD_BYTES_LINE; i++)
*linebuf++ = swap(*frmbufptr++); //swap the order of the bits
*linebuf++ = 0; //trailer
//Setup the SPI DMA controller (starting addr, size)
TransferSetup(locbuf, linebuf - locbuf);
//Start the xfer
TransferStart;
stage = 1; //set to next stage
break;
case 1: //Sending a line (other than the first line). At this
//point the DMA transfer for the previous line is done
//and the channel disabled.
linebuf = locbuf; //init pointer to line buffer
*linebuf++ = swap(linenum++); //line number
for (i=0; i<MLCD_BYTES_LINE; i++)
*linebuf++ = swap(*frmbufptr++); //swap the order of the bits
*linebuf++ = 0; //trailer
//set up DMA control
TransferSetup(locbuf, linebuf - locbuf);
//Start the xfer
TransferStart;
if (linenum > MLCD_YRES)
stage = 2; //all lines sent, go to next stage
break;
case 2:
// All lines sent, send a fi nal null byte trailer. The DMA
//transfer of the last line is fi nished and the channel
//disabled. All that is left is to write a trailing null
//byte. Its not worth using DMA to transfer 1 byte, so
//its done by directing writing to the SPI port.
//Write the last (null) byte
Write_to_SPI(0);
//Since there is no interrupt on transmit buffer empty, loop
//here until the byte is sent, then drop SCS.
i = 0;
while (SPI_BSY); //wait until done
set_scs(LOW);
stage = 0; //go back to stage 0 - sending out first line
}
}