RaspberryLCD/raspberrylcd.c

285 lines
13 KiB
C
Raw Permalink Normal View History

2020-11-19 22:12:36 +00:00
#include "raspberrylcd.h"
#include <wiringPi.h>
#include <stdio.h>
2020-11-20 00:32:33 +00:00
#include <stdarg.h>
2020-11-19 22:12:36 +00:00
void waitMs(uint32_t ms)
{
delay(ms);
}
LCDScreen* configurePins(LCDScreen* screen, uint8_t RS, uint8_t RW, uint8_t E,
uint8_t D0, uint8_t D1, uint8_t D2, uint8_t D3,
uint8_t D4, uint8_t D5, uint8_t D6, uint8_t D7)
{
2020-11-20 15:53:27 +00:00
// Simply set all the fields to the supplied pins
2020-11-19 22:12:36 +00:00
screen->RS = RS;
screen->RW = RW;
screen->E = E;
screen->D0 = D0;
screen->D1 = D1;
screen->D2 = D2;
screen->D3 = D3;
screen->D4 = D4;
screen->D5 = D5;
screen->D6 = D6;
screen->D7 = D7;
2020-11-20 15:53:27 +00:00
// Initialize the pins to be output
2020-11-19 22:12:36 +00:00
wiringPiSetup();
pinMode(screen->RS, OUTPUT);
pinMode(screen->RW, OUTPUT);
pinMode(screen->E, OUTPUT);
pinMode(screen->D0, OUTPUT);
pinMode(screen->D1, OUTPUT);
pinMode(screen->D2, OUTPUT);
pinMode(screen->D3, OUTPUT);
pinMode(screen->D4, OUTPUT);
pinMode(screen->D5, OUTPUT);
pinMode(screen->D6, OUTPUT);
pinMode(screen->D7, OUTPUT);
return screen;
}
void initScreen(LCDScreen* screen, uint8_t interface_bits, uint8_t num_lines, uint8_t fontType, uint8_t cursor, uint8_t writeDirection)
{
2020-11-20 15:53:27 +00:00
// Set interface bits of screen
2020-11-19 22:12:36 +00:00
screen->interface_bits = interface_bits;
2020-11-20 15:53:27 +00:00
// Tell LCD screen to operate in intended bit mode
sendCommand(screen, (FUNCTION_SET | interface_bits) >> 4);
2020-11-19 22:12:36 +00:00
2020-11-20 15:53:27 +00:00
// Set number of display lines and font type
2020-11-19 22:12:36 +00:00
sendCommand(screen, FUNCTION_SET | num_lines | fontType);
2020-11-20 15:53:27 +00:00
// Turn display on and set cursor
2020-11-19 22:12:36 +00:00
sendCommand(screen, DISPLAY_SWITCH | DISPLAY_ON | cursor);
2020-11-20 15:53:27 +00:00
// Clear screen
2020-11-19 22:12:36 +00:00
sendCommand(screen, SCREEN_CLEAR);
2020-11-20 15:53:27 +00:00
// Set write direction
2020-11-19 22:12:36 +00:00
sendCommand(screen, INPUT_SET | writeDirection);
}
void resetPins(LCDScreen* screen)
{
2020-11-20 15:53:27 +00:00
// Pull all pins low
2020-11-19 22:12:36 +00:00
digitalWrite(screen->D7, LOW);
digitalWrite(screen->D6, LOW);
digitalWrite(screen->D5, LOW);
digitalWrite(screen->D4, LOW);
digitalWrite(screen->D3, LOW);
digitalWrite(screen->D2, LOW);
digitalWrite(screen->D1, LOW);
digitalWrite(screen->D0, LOW);
digitalWrite(screen->E, LOW);
digitalWrite(screen->RW, LOW);
digitalWrite(screen->RS, LOW);
}
2020-11-20 15:53:27 +00:00
// A helper function to send bytes to the screen
// This function is not visible to the user
2020-11-19 22:12:36 +00:00
void helper_send(LCDScreen* screen, uint8_t byte)
{
2020-11-20 15:53:27 +00:00
// Pull Enable high
2020-11-19 22:12:36 +00:00
digitalWrite(screen->E, HIGH);
2020-11-20 15:53:27 +00:00
// Write high nibble
2020-11-19 22:12:36 +00:00
digitalWrite(screen->D7, (byte >> 7) & 0x1);
digitalWrite(screen->D6, (byte >> 6) & 0x1);
digitalWrite(screen->D5, (byte >> 5) & 0x1);
digitalWrite(screen->D4, (byte >> 4) & 0x1);
2020-11-20 15:53:27 +00:00
// If we're in 8-bit mode, write the lower nibbles as well
2020-11-19 22:12:36 +00:00
if(screen->interface_bits == FULL_BYTE_INTERFACE)
{
digitalWrite(screen->D3, (byte >> 3) & 0x1);
digitalWrite(screen->D2, (byte >> 2) & 0x1);
digitalWrite(screen->D1, (byte >> 1) & 0x1);
digitalWrite(screen->D0, (byte >> 0) & 0x1);
}
2020-11-20 15:53:27 +00:00
// If in 4-bit, then send the high nibbles and then set the lower nibbles
2020-11-19 22:12:36 +00:00
else if(screen->interface_bits == HALF_BYTE_INTERFACE)
{
delayMicroseconds(1000);
digitalWrite(screen->E, LOW);
delayMicroseconds(10000);
digitalWrite(screen->E, HIGH);
digitalWrite(screen->D7, (byte >> 3) & 0x1);
digitalWrite(screen->D6, (byte >> 2) & 0x1);
digitalWrite(screen->D5, (byte >> 1) & 0x1);
digitalWrite(screen->D4, (byte >> 0) & 0x1);
}
2020-11-20 15:53:27 +00:00
// Send the data supplied on the pins
2020-11-19 22:12:36 +00:00
delayMicroseconds(1000);
digitalWrite(screen->E, LOW);
delayMicroseconds(10000);
}
2020-11-20 15:53:27 +00:00
// Sends a command by pulling RW and RS low
2020-11-19 22:12:36 +00:00
void sendCommand(LCDScreen* screen, uint8_t command)
{
digitalWrite(screen->RW, LOW);
digitalWrite(screen->RS, LOW);
helper_send(screen, command);
}
2020-11-20 15:53:27 +00:00
// Sends a character by pulling only RW low
2020-11-19 22:12:36 +00:00
void sendData(LCDScreen* screen, uint8_t data)
{
digitalWrite(screen->RW, LOW);
digitalWrite(screen->RS, HIGH);
helper_send(screen, data);
}
2020-11-20 15:53:27 +00:00
// Loops over a char* and sends each character individually. Supports the katakana and math as well
2020-11-19 22:12:36 +00:00
void sendText(LCDScreen* screen, const char* text)
{
for(const char* c = text; *c != '\x00'; c++)
2020-11-20 01:03:03 +00:00
{
2020-11-20 12:37:20 +00:00
if(*c == '\xe3')
2020-11-20 01:03:03 +00:00
{
uint16_t symbol = ((uint16_t)(*(c + 1)) << 8) | ((uint16_t)(*(c + 2)));
switch(symbol)
{
2020-11-20 11:50:52 +00:00
/* */ case 0x8080: sendData(screen, ' '); break;
/*、*/ case 0x8081: sendData(screen, JAPANESE_COMMA); break;
/*。*/ case 0x8082: sendData(screen, JAPANESE_PERIOD); break;
/*「*/ case 0x808C: sendData(screen, JAPANESE_QUOTE_START); break;
/*」*/ case 0x808D: sendData(screen, JAPANESE_QUOTE_END); break;
/*ァ*/ case 0x82A1: sendData(screen, JAPANESE_KATAKANA_CHIISAI_A); break;
/*ア*/ case 0x82A2: sendData(screen, JAPANESE_KATAKANA_A); break;
/*ィ*/ case 0x82A3: sendData(screen, JAPANESE_KATAKANA_CHIISAI_I); break;
/*イ*/ case 0x82A4: sendData(screen, JAPANESE_KATAKANA_I); break;
/*ゥ*/ case 0x82A5: sendData(screen, JAPANESE_KATAKANA_CHIISAI_U); break;
/*ウ*/ case 0x82A6: sendData(screen, JAPANESE_KATAKANA_U); break;
/*ェ*/ case 0x82A7: sendData(screen, JAPANESE_KATAKANA_CHIISAI_E); break;
/*エ*/ case 0x82A8: sendData(screen, JAPANESE_KATAKANA_E); break;
/*ォ*/ case 0x82A9: sendData(screen, JAPANESE_KATAKANA_CHIISAI_O); break;
/*オ*/ case 0x82AA: sendData(screen, JAPANESE_KATAKANA_O); break;
/*カ*/ case 0x82AB: sendData(screen, JAPANESE_KATAKANA_KA); break;
/*ガ*/ case 0x82AC: sendChars(screen, 2, JAPANESE_KATAKANA_KA, JAPANESE_DAKUTEN); break;
/*キ*/ case 0x82AD: sendData(screen, JAPANESE_KATAKANA_KI); break;
/*ギ*/ case 0x82AE: sendChars(screen, 2, JAPANESE_KATAKANA_KI, JAPANESE_DAKUTEN); break;
/*ク*/ case 0x82AF: sendData(screen, JAPANESE_KATAKANA_KU); break;
/*グ*/ case 0x82B0: sendChars(screen, 2, JAPANESE_KATAKANA_KU, JAPANESE_DAKUTEN); break;
/*ケ*/ case 0x82B1: sendData(screen, JAPANESE_KATAKANA_KE); break;
/*ゲ*/ case 0x82B2: sendChars(screen, 2, JAPANESE_KATAKANA_KE, JAPANESE_DAKUTEN); break;
/*コ*/ case 0x82B3: sendData(screen, JAPANESE_KATAKANA_KO); break;
/*ゴ*/ case 0x82B4: sendChars(screen, 2, JAPANESE_KATAKANA_KO, JAPANESE_DAKUTEN); break;
/*サ*/ case 0x82B5: sendData(screen, JAPANESE_KATAKANA_SA); break;
/*ザ*/ case 0x82B6: sendChars(screen, 2, JAPANESE_KATAKANA_SA, JAPANESE_DAKUTEN); break;
/*シ*/ case 0x82B7: sendData(screen, JAPANESE_KATAKANA_SHI); break;
/*ジ*/ case 0x82B8: sendChars(screen, 2, JAPANESE_KATAKANA_SHI, JAPANESE_DAKUTEN); break;
/*ス*/ case 0x82B9: sendData(screen, JAPANESE_KATAKANA_SU); break;
/*ズ*/ case 0x82BA: sendChars(screen, 2, JAPANESE_KATAKANA_SU, JAPANESE_DAKUTEN); break;
/*セ*/ case 0x82BB: sendData(screen, JAPANESE_KATAKANA_SE); break;
/*ゼ*/ case 0x82BC: sendChars(screen, 2, JAPANESE_KATAKANA_SE, JAPANESE_DAKUTEN); break;
/*ソ*/ case 0x82BD: sendData(screen, JAPANESE_KATAKANA_SO); break;
/*ゾ*/ case 0x82BE: sendChars(screen, 2, JAPANESE_KATAKANA_SO, JAPANESE_DAKUTEN); break;
/*タ*/ case 0x82BF: sendData(screen, JAPANESE_KATAKANA_TA); break;
/*ダ*/ case 0x8380: sendChars(screen, 2, JAPANESE_KATAKANA_TA, JAPANESE_DAKUTEN); break;
/*チ*/ case 0x8381: sendData(screen, JAPANESE_KATAKANA_CHI); break;
/*ヂ*/ case 0x8382: sendChars(screen, 2, JAPANESE_KATAKANA_CHI, JAPANESE_DAKUTEN); break;
/*ッ*/ case 0x8383: sendData(screen, JAPANESE_KATAKANA_CHIISAI_TSU); break;
/*ツ*/ case 0x8384: sendData(screen, JAPANESE_KATAKANA_TSU); break;
/*ヅ*/ case 0x8385: sendChars(screen, 2, JAPANESE_KATAKANA_TSU, JAPANESE_DAKUTEN); break;
/*テ*/ case 0x8386: sendData(screen, JAPANESE_KATAKANA_TE); break;
/*デ*/ case 0x8387: sendChars(screen, 2, JAPANESE_KATAKANA_TE, JAPANESE_DAKUTEN); break;
/*ト*/ case 0x8388: sendData(screen, JAPANESE_KATAKANA_TO); break;
/*ド*/ case 0x8389: sendChars(screen, 2, JAPANESE_KATAKANA_TO, JAPANESE_DAKUTEN); break;
/*ナ*/ case 0x838A: sendData(screen, JAPANESE_KATAKANA_NA); break;
/*ニ*/ case 0x838B: sendData(screen, JAPANESE_KATAKANA_NI); break;
/*ヌ*/ case 0x838C: sendData(screen, JAPANESE_KATAKANA_NU); break;
/*ネ*/ case 0x838D: sendData(screen, JAPANESE_KATAKANA_NE); break;
/**/ case 0x838E: sendData(screen, JAPANESE_KATAKANA_NO); break;
/*ハ*/ case 0x838F: sendData(screen, JAPANESE_KATAKANA_HA); break;
/*バ*/ case 0x8390: sendChars(screen, 2, JAPANESE_KATAKANA_HA, JAPANESE_DAKUTEN); break;
/*パ*/ case 0x8391: sendChars(screen, 2, JAPANESE_KATAKANA_HA, JAPANESE_HANDAKUTEN); break;
/*ヒ*/ case 0x8392: sendData(screen, JAPANESE_KATAKANA_HI); break;
/*ビ*/ case 0x8393: sendChars(screen, 2, JAPANESE_KATAKANA_HI, JAPANESE_DAKUTEN); break;
/*ピ*/ case 0x8394: sendChars(screen, 2, JAPANESE_KATAKANA_HI, JAPANESE_HANDAKUTEN); break;
/*フ*/ case 0x8395: sendData(screen, JAPANESE_KATAKANA_FU); break;
/*ブ*/ case 0x8396: sendChars(screen, 2, JAPANESE_KATAKANA_FU, JAPANESE_DAKUTEN); break;
/*プ*/ case 0x8397: sendChars(screen, 2, JAPANESE_KATAKANA_FU, JAPANESE_HANDAKUTEN); break;
/*ヘ*/ case 0x8398: sendData(screen, JAPANESE_KATAKANA_HE); break;
/*ベ*/ case 0x8399: sendChars(screen, 2, JAPANESE_KATAKANA_HE, JAPANESE_DAKUTEN); break;
/*ペ*/ case 0x839A: sendChars(screen, 2, JAPANESE_KATAKANA_HE, JAPANESE_HANDAKUTEN); break;
/*ホ*/ case 0x839B: sendData(screen, JAPANESE_KATAKANA_HO); break;
/*ボ*/ case 0x839C: sendChars(screen, 2, JAPANESE_KATAKANA_HO, JAPANESE_DAKUTEN); break;
/*ポ*/ case 0x839D: sendChars(screen, 2, JAPANESE_KATAKANA_HO, JAPANESE_HANDAKUTEN); break;
/*マ*/ case 0x839E: sendData(screen, JAPANESE_KATAKANA_MA); break;
/*ミ*/ case 0x839F: sendData(screen, JAPANESE_KATAKANA_MI); break;
/*ム*/ case 0x83A0: sendData(screen, JAPANESE_KATAKANA_MU); break;
/*メ*/ case 0x83A1: sendData(screen, JAPANESE_KATAKANA_ME); break;
/*モ*/ case 0x83A2: sendData(screen, JAPANESE_KATAKANA_MO); break;
/*ャ*/ case 0x83A3: sendData(screen, JAPANESE_KATAKANA_CHIISAI_YA); break;
/*ヤ*/ case 0x83A4: sendData(screen, JAPANESE_KATAKANA_YA); break;
/*ュ*/ case 0x83A5: sendData(screen, JAPANESE_KATAKANA_CHIISAI_YU); break;
/*ユ*/ case 0x83A6: sendData(screen, JAPANESE_KATAKANA_YU); break;
/*ョ*/ case 0x83A7: sendData(screen, JAPANESE_KATAKANA_CHIISAI_YO); break;
/*ヨ*/ case 0x83A8: sendData(screen, JAPANESE_KATAKANA_YO); break;
/*ラ*/ case 0x83A9: sendData(screen, JAPANESE_KATAKANA_RA); break;
/*リ*/ case 0x83AA: sendData(screen, JAPANESE_KATAKANA_RI); break;
/*ル*/ case 0x83AB: sendData(screen, JAPANESE_KATAKANA_RU); break;
/*レ*/ case 0x83AC: sendData(screen, JAPANESE_KATAKANA_RE); break;
/*ロ*/ case 0x83AD: sendData(screen, JAPANESE_KATAKANA_RO); break;
/*ワ*/ case 0x83AF: sendData(screen, JAPANESE_KATAKANA_WA); break;
/*ヲ*/ case 0x83B2: sendData(screen, JAPANESE_KATAKANA_WO); break;
/*ン*/ case 0x83B3: sendData(screen, JAPANESE_KATAKANA_N); break;
/*ヴ*/ case 0x83B4: sendChars(screen, 2, JAPANESE_KATAKANA_U, JAPANESE_DAKUTEN); break;
/*ヴ*/ case 0x83B5: sendChars(screen, 2, JAPANESE_KATAKANA_WA, JAPANESE_DAKUTEN); break;
/*ヺ*/ case 0x83BA: sendChars(screen, 2, JAPANESE_KATAKANA_WO, JAPANESE_DAKUTEN); break;
/*・*/ case 0x83BB: sendData(screen, JAPANESE_INTERPUNCT); break;
/*ー*/ case 0x83BC: sendData(screen, JAPANESE_CHOONPU); break;
2020-11-20 01:03:03 +00:00
default: printf("Unknown char: %x\n", symbol); sendData(screen, CURSOR); break;
}
c += 2;
}
2020-11-20 12:37:20 +00:00
else
{
sendData(screen, *c);
}
2020-11-20 01:03:03 +00:00
}
2020-11-20 00:32:33 +00:00
}
2020-11-20 15:53:27 +00:00
// Sends a list of chars, similar to sendText
2020-11-20 00:32:33 +00:00
void sendChars(LCDScreen* screen, size_t len, ...)
{
va_list args;
va_start(args, len);
for(size_t i = 0; i < len; i++)
sendData(screen, (uint8_t)va_arg(args, int));
va_end(args);
2020-11-20 12:37:20 +00:00
}
2020-11-20 14:44:34 +00:00
2020-11-20 15:53:27 +00:00
// Loads a custom character into CGRAM
2020-11-20 14:44:34 +00:00
void loadCustomChar(LCDScreen* screen, uint8_t cgram_addr, ...)
{
2020-11-20 15:53:27 +00:00
// Initialize va_args
2020-11-20 14:44:34 +00:00
va_list args;
va_start(args, cgram_addr);
2020-11-20 15:53:27 +00:00
// Choose correct scram address
2020-11-20 14:44:34 +00:00
sendCommand(screen, CGRAM_AD_SET | (cgram_addr << 3));
2020-11-20 15:53:27 +00:00
// Write data to RAM
2020-11-20 14:44:34 +00:00
for(int i = 0; i < 8; i++)
sendData(screen, va_arg(args, int));
2020-11-20 15:53:27 +00:00
// Free va_args
2020-11-20 14:44:34 +00:00
va_end(args);
}