/* P12_1.c: PCD8544 (Nokia5110) GLCD via SPI with SAMD21 * * Letters A,B,C are written on the display. * * Interface uses SERCOM1 of SAMD21 Xplained Pro board. * * PA16 PAD0 MOSI * PA17 PAD1 SCK * PA18 SS (hardware slave select) * PA08 register select (DC) * PA09 reset * * Tested with Atmel Studio 7 v7.0.1006 and Keil MDK-ARM v5.21a. */ #include "samd21.h" #define RESET 0x200 /* PA09 reset */ #define DC 0x100 /* PA08 register select */ /* define the pixel size of display */ #define GLCD_WIDTH 84 #define GLCD_HEIGHT 48 void GLCD_setCursor(unsigned char x, unsigned char y); void GLCD_clear(void); void GLCD_init(void); void GLCD_data_write(unsigned char data); void GLCD_command_write(unsigned char data); void GLCD_putchar(int c); void SPI_init(void); void SPI_write(unsigned char data); unsigned char* ARRAY_PORT_PINCFG0 = (unsigned char*)®_PORT_PINCFG0; unsigned char* ARRAY_PORT_PMUX0 = (unsigned char*)®_PORT_PMUX0; /* sample font table */ const char font_table[][6] = { {0x7e, 0x11, 0x11, 0x11, 0x7e, 0}, /* A */ {0x7f, 0x49, 0x49, 0x49, 0x36, 0}, /* B */ {0x3e, 0x41, 0x41, 0x41, 0x22, 0} /* C */ }; int main(void) { GLCD_init(); /* initialize the GLCD controller */ GLCD_clear(); /* clear display and home the cursor */ GLCD_putchar(0); /* display letter A */ GLCD_putchar(1); /* display letter B */ GLCD_putchar(2); /* display letter C */ while(1) { } } void GLCD_putchar(int c) { int i; for (i = 0; i < 6; i++) GLCD_data_write(font_table[c][i]); } void GLCD_setCursor(unsigned char x, unsigned char y) { GLCD_command_write(0x80 | x); /* column */ GLCD_command_write(0x40 | y); /* bank (8 pixel rows per bank) */ } /* clears the GLCD by writing zeros to the entire screen */ void GLCD_clear(void) { int32_t index; for (index = 0 ; index < (GLCD_WIDTH * GLCD_HEIGHT / 8) ; index++) GLCD_data_write(0x00); GLCD_setCursor(0, 0); /* return to the home position */ } /* send the initialization commands to PCD8544 GLCD controller */ void GLCD_init(void) { SPI_init(); /* hardware reset of GLCD controller */ REG_PORT_OUTSET0 = RESET; /* deassert reset */ GLCD_command_write(0x21); /* set extended command mode */ GLCD_command_write(0xB8); /* set LCD Vop for contrast */ GLCD_command_write(0x04); /* set temp coefficient */ GLCD_command_write(0x14); /* set LCD bias mode 1:48 */ GLCD_command_write(0x20); /* set normal command mode */ GLCD_command_write(0x0C); /* set display normal mode */ } /* write to GLCD controller data register */ void GLCD_data_write(unsigned char data) { REG_PORT_OUTSET0 = DC; /* select data register */ SPI_write(data); /* send data via SPI */ } /* write to GLCD controller command register */ void GLCD_command_write(unsigned char data) { REG_PORT_OUTCLR0 = DC; /* select command register */ SPI_write(data); /* send data via SPI */ } void SPI_init(void) { REG_PM_APBCMASK |= 0x00000008; /* SERCOM1 bus clock */ REG_GCLK_CLKCTRL = 0x4015; /* SERCOM1 core clock */ ARRAY_PORT_PINCFG0[16] |= 1; /* allow pmux to set PA16 pin configuration */ ARRAY_PORT_PINCFG0[17] |= 1; /* allow pmux to set PA17 pin configuration */ ARRAY_PORT_PINCFG0[18] |= 1; /* allow pmux to set PA18 pin configuration */ ARRAY_PORT_PINCFG0[19] |= 1; /* allow pmux to set PA19 pin configuration */ ARRAY_PORT_PMUX0[8] = 0x22; /* PA16 = MOSI, PA17 = SCK */ ARRAY_PORT_PMUX0[9] = 0x22; /* PA18 = SS, PA19 = MISO */ REG_SERCOM1_SPI_CTRLA = 1; /* reset SERCOM1 */ while (REG_SERCOM1_SPI_CTRLA & 1) {} /* wait for reset to complete */ REG_SERCOM1_SPI_CTRLA = 0x0030000C; /* MISO-3, MOSI-0, SCK-1, SS-2, SPI master */ REG_SERCOM1_SPI_CTRLB = 0x00002000; /* Master SS, 8-bit */ REG_SERCOM1_SPI_BAUD = 0; /* SPI clock is 1MHz/2 = 500kHz */ REG_SERCOM1_SPI_CTRLA |= 2; /* enable SERCOM1 */ REG_PORT_DIRSET0 = RESET | DC; /* PA08, PA09 set as output */ REG_PORT_OUTCLR0 = RESET; /* assert reset */ } void SPI_write(unsigned char data) { while(!(REG_SERCOM1_SPI_INTFLAG & 1)) {} /* wait until Tx ready */ REG_SERCOM1_SPI_DATA = data; /* send data byte */ }