oswald/metawatch/sharp_mem_lcd.c
2021-02-14 18:03:13 +01:00

113 lines
3.8 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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
}
}