-
-
Save JohnWulff/29f216a7d79d09807712 to your computer and use it in GitHub Desktop.
Show text corruptions and other errors for pifacecad.c in libpifacecad
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <time.h> | |
#include <stdint.h> | |
#include <unistd.h> | |
#include <mcp23s17.h> | |
#include "pifacecad.h" | |
/******************************************************************** | |
* | |
* Reset microsecend timer at program start | |
* Print microseconds since last call to microPrint | |
* | |
*******************************************************************/ | |
#include <sys/time.h> | |
#include <math.h> | |
#define ARRAYSIZE 1000 | |
static struct timeval mt0; | |
static struct timeval mt1; | |
static int index = 0; | |
static int start = 0; | |
static long array[ARRAYSIZE]; | |
void | |
microReset(void) | |
{ | |
gettimeofday(&mt0, 0); /* reset for next measurement */ | |
start = index; | |
} /* microReset */ | |
void | |
microPrint(const char * str, unsigned data) | |
{ | |
long sec; | |
long usec; | |
int n; | |
long sum; | |
double mean; | |
double diff; | |
double sumsq; | |
double stddeviation; | |
if (gettimeofday(&mt1, 0) == 0) { | |
sec = mt1.tv_sec - mt0.tv_sec; | |
usec = mt1.tv_usec - mt0.tv_usec; | |
if (usec < 0) { | |
sec--; | |
usec += 1000000; | |
} | |
if (index >= ARRAYSIZE) { | |
sum = 0; | |
for (n = 0; n < ARRAYSIZE; n++) { | |
sum += array[n]; | |
} | |
mean = (double)sum / ARRAYSIZE; | |
sumsq = 0.0; | |
for (n = 0; n < ARRAYSIZE; n++) { | |
diff = (double)array[n] - mean; | |
sumsq += (diff * diff); | |
} | |
stddeviation = sqrt(sumsq / (ARRAYSIZE-1)); | |
printf("================================\n"); | |
printf("MEAN = %6.2f us STANDARD DEVIATION = %6.2f\n", mean, stddeviation); | |
printf("================================\n"); | |
start = index = 0; | |
} | |
if (str) { | |
printf("%3ld.%03ld,%03ld: %s0x%02x)", sec, usec/1000, usec%1000, str, data); | |
for (n = start; n < index; n++) { | |
printf(" %ld", array[n]); | |
} | |
printf("\n"); | |
} | |
if (sec == 0 && usec < 1000) array[index++] = usec; /* ignore seconds */ | |
} | |
gettimeofday(&mt0, 0); /* start of next measurement without print time */ | |
} /* microPrint */ | |
// PiFace Control and Display is always at /dev/spidev0.1, hw_addr = 0 | |
static const int bus = 0, chip_select = 1, hw_addr = 0; | |
static int mcp23s17_fd = 0; // MCP23S17 SPI file descriptor | |
static const int SWITCH_PORT = GPIOA; | |
/* LCD_PORT (GPIOB) looks like: | |
* +-----------+----+----+----+--------------------+--------+--------+--------+ | |
* | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | | |
* +-----------+----+----+----+--------------------+--------+--------+--------+ | |
* | backlight | rs | rw | en | data 7 / busy flag | data 6 | data 5 | data 4 | | |
* +-----------+----+----+----+--------------------+--------+--------+--------+ | |
*/ | |
static const int LCD_PORT = GPIOB; | |
// current lcd state | |
// static int curcol = 0, currow = 0; | |
static uint8_t cur_address = 0; | |
static uint8_t cur_entry_mode = 0; | |
static uint8_t cur_function_set = 0; | |
static uint8_t cur_display_control = 0; | |
// static function definitions | |
static void sleep_ns(long nanoseconds); | |
static int max(int a, int b); | |
static int min(int a, int b); | |
static uint8_t is_busy(void); | |
int pifacecad_open_noinit(void) | |
{ | |
// All PiFace Digital are connected to the same SPI bus, only need 1 fd. | |
if ((mcp23s17_fd = mcp23s17_open(bus, chip_select)) < 0) { | |
return -1; | |
} | |
return mcp23s17_fd; // returns the fd in case user wants to use it | |
} | |
int pifacecad_open(void) | |
{ | |
pifacecad_open_noinit(); | |
// Set IO config | |
const uint8_t ioconfig = BANK_OFF | \ | |
INT_MIRROR_OFF | \ | |
SEQOP_ON | \ | |
DISSLW_OFF | \ | |
HAEN_ON | \ | |
ODR_OFF | \ | |
INTPOL_LOW; | |
mcp23s17_write_reg(ioconfig, IOCON, hw_addr, mcp23s17_fd); | |
// Set GPIO Port A as inputs (switches) | |
mcp23s17_write_reg(0xff, IODIRA, hw_addr, mcp23s17_fd); | |
mcp23s17_write_reg(0xff, GPPUA, hw_addr, mcp23s17_fd); | |
// Set GPIO Port B as outputs (connected to HD44780) | |
mcp23s17_write_reg(0x00, IODIRB, hw_addr, mcp23s17_fd); | |
// enable interrupts | |
mcp23s17_write_reg(0xFF, GPINTENA, hw_addr, mcp23s17_fd); | |
pifacecad_lcd_init(); | |
return mcp23s17_fd; | |
} | |
void pifacecad_close(void) | |
{ | |
// disable interrupts if enabled | |
const uint8_t intenb = mcp23s17_read_reg(GPINTENA, hw_addr, mcp23s17_fd); | |
if (intenb) { | |
mcp23s17_write_reg(0, GPINTENA, hw_addr, mcp23s17_fd); | |
// now do some other interrupt stuff... | |
// TODO | |
} | |
close(mcp23s17_fd); | |
} | |
void pifacecad_lcd_init(void) | |
{ | |
// setup sequence | |
sleep_ns(DELAY_SETUP_0_NS); | |
mcp23s17_write_reg(0x3, LCD_PORT, hw_addr, mcp23s17_fd); | |
pifacecad_lcd_pulse_enable(); | |
sleep_ns(DELAY_SETUP_1_NS); | |
mcp23s17_write_reg(0x3, LCD_PORT, hw_addr, mcp23s17_fd); | |
pifacecad_lcd_pulse_enable(); | |
sleep_ns(DELAY_SETUP_2_NS); | |
mcp23s17_write_reg(0x3, LCD_PORT, hw_addr, mcp23s17_fd); | |
pifacecad_lcd_pulse_enable(); | |
mcp23s17_write_reg(0x2, LCD_PORT, hw_addr, mcp23s17_fd); | |
pifacecad_lcd_pulse_enable(); | |
/* don't use the `pifacecad_lcd_send_command` function for the rest | |
* because we wan't to ignore the busy flag during initialisation so | |
* that we can recover from a dirty exit (eg. Ctrl-C). | |
*/ | |
pifacecad_lcd_set_rs(0); | |
cur_function_set |= LCD_4BITMODE | LCD_2LINE | LCD_5X8DOTS; | |
// pifacecad_lcd_send_command(LCD_FUNCTIONSET | cur_function_set); | |
pifacecad_lcd_send_byte(LCD_FUNCTIONSET | cur_function_set); | |
sleep_ns(DELAY_SETTLE_NS); | |
cur_display_control |= LCD_DISPLAYOFF | LCD_CURSOROFF | LCD_BLINKOFF; | |
// pifacecad_lcd_send_command(LCD_DISPLAYCONTROL | cur_display_control); | |
pifacecad_lcd_send_byte(LCD_DISPLAYCONTROL | cur_display_control); | |
sleep_ns(DELAY_SETTLE_NS); | |
// pifacecad_lcd_clear(); | |
pifacecad_lcd_send_byte(LCD_CLEARDISPLAY); | |
sleep_ns(DELAY_SETTLE_NS); | |
cur_entry_mode |= LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; | |
// pifacecad_lcd_send_command(LCD_ENTRYMODESET | cur_entry_mode); | |
pifacecad_lcd_send_byte(LCD_ENTRYMODESET | cur_entry_mode); | |
sleep_ns(DELAY_SETTLE_NS); | |
cur_display_control |= LCD_DISPLAYON | LCD_CURSORON | LCD_BLINKON; | |
// pifacecad_lcd_send_command(LCD_DISPLAYCONTROL | cur_display_control); | |
pifacecad_lcd_send_byte(LCD_DISPLAYCONTROL | cur_display_control); | |
sleep_ns(DELAY_SETTLE_NS); | |
} | |
uint8_t pifacecad_read_switches(void) | |
{ | |
return mcp23s17_read_reg(SWITCH_PORT, hw_addr, mcp23s17_fd); | |
} | |
uint8_t pifacecad_read_switch(uint8_t switch_num) | |
{ | |
return (mcp23s17_read_reg(SWITCH_PORT, | |
hw_addr, | |
mcp23s17_fd) >> switch_num) & 1; | |
} | |
int pifacecad_enable_interrupts() | |
{ | |
return mcp23s17_enable_interrupts(); | |
} | |
int pifacecad_disable_interrupts() | |
{ | |
return mcp23s17_disable_interrupts(); | |
} | |
uint8_t pifacecad_wait_for_switch(int timeout) | |
{ | |
// Flush any pending interrupts prior to wait | |
mcp23s17_read_reg(INTCAPA, hw_addr, mcp23s17_fd); | |
// Wait for input state change | |
mcp23s17_wait_for_interrupt(timeout); | |
// Read & return input register, thus clearing interrupt | |
return mcp23s17_read_reg(INTCAPA, hw_addr, mcp23s17_fd); | |
} | |
uint8_t pifacecad_lcd_write(const char * message) | |
{ | |
pifacecad_lcd_send_command(LCD_SETDDRAMADDR | cur_address); | |
// for each character in the message | |
while (*message) { | |
if (*message == '\n') { | |
pifacecad_lcd_set_cursor(0, 1); | |
} else { | |
pifacecad_lcd_send_data(*message); | |
cur_address++; | |
} | |
message++; | |
} | |
return cur_address; | |
} | |
uint8_t pifacecad_lcd_set_cursor(uint8_t col, uint8_t row) | |
{ | |
col = max(0, min(col, (LCD_RAM_WIDTH / 2) - 1)); | |
row = max(0, min(row, LCD_MAX_LINES - 1)); | |
pifacecad_lcd_set_cursor_address(colrow2address(col, row)); | |
return cur_address; | |
} | |
void pifacecad_lcd_set_cursor_address(uint8_t address) | |
{ | |
cur_address = address % LCD_RAM_WIDTH; | |
pifacecad_lcd_send_command(LCD_SETDDRAMADDR | cur_address); | |
} | |
uint8_t pifacecad_lcd_get_cursor_address(void) | |
{ | |
return cur_address; | |
} | |
void pifacecad_lcd_clear(void) | |
{ | |
pifacecad_lcd_send_command(LCD_CLEARDISPLAY); | |
cur_address = 0; | |
} | |
void pifacecad_lcd_home(void) | |
{ | |
pifacecad_lcd_send_command(LCD_RETURNHOME); | |
cur_address = 0; | |
} | |
void pifacecad_lcd_display_on(void) | |
{ | |
cur_display_control |= LCD_DISPLAYON; | |
pifacecad_lcd_send_command(LCD_DISPLAYCONTROL | cur_display_control); | |
} | |
void pifacecad_lcd_display_off(void) | |
{ | |
cur_display_control &= 0xff ^ LCD_DISPLAYON; | |
pifacecad_lcd_send_command(LCD_DISPLAYCONTROL | cur_display_control); | |
} | |
void pifacecad_lcd_blink_on(void) | |
{ | |
cur_display_control |= LCD_BLINKON; | |
pifacecad_lcd_send_command(LCD_DISPLAYCONTROL | cur_display_control); | |
} | |
void pifacecad_lcd_blink_off(void) | |
{ | |
cur_display_control &= 0xff ^ LCD_BLINKON; | |
pifacecad_lcd_send_command(LCD_DISPLAYCONTROL | cur_display_control); | |
} | |
void pifacecad_lcd_cursor_on(void) | |
{ | |
cur_display_control |= LCD_CURSORON; | |
pifacecad_lcd_send_command(LCD_DISPLAYCONTROL | cur_display_control); | |
} | |
void pifacecad_lcd_cursor_off(void) | |
{ | |
cur_display_control &= 0xff ^ LCD_CURSORON; | |
pifacecad_lcd_send_command(LCD_DISPLAYCONTROL | cur_display_control); | |
} | |
void pifacecad_lcd_backlight_on(void) | |
{ | |
pifacecad_lcd_set_backlight(1); | |
} | |
void pifacecad_lcd_backlight_off(void) | |
{ | |
pifacecad_lcd_set_backlight(0); | |
} | |
void pifacecad_lcd_move_left(void) | |
{ | |
pifacecad_lcd_send_command(LCD_CURSORSHIFT | \ | |
LCD_DISPLAYMOVE | \ | |
LCD_MOVELEFT); | |
} | |
void pifacecad_lcd_move_right(void) | |
{ | |
pifacecad_lcd_send_command(LCD_CURSORSHIFT | \ | |
LCD_DISPLAYMOVE | \ | |
LCD_MOVERIGHT); | |
} | |
void pifacecad_lcd_left_to_right(void) | |
{ | |
cur_entry_mode |= LCD_ENTRYLEFT; | |
pifacecad_lcd_send_command(LCD_ENTRYMODESET | cur_entry_mode); | |
} | |
void pifacecad_lcd_right_to_left(void) | |
{ | |
cur_entry_mode &= 0xff ^ LCD_ENTRYLEFT; | |
pifacecad_lcd_send_command(LCD_ENTRYMODESET | cur_entry_mode); | |
} | |
// This will 'right justify' text from the cursor | |
void pifacecad_lcd_autoscroll_on(void) | |
{ | |
cur_display_control |= LCD_ENTRYSHIFTINCREMENT; | |
pifacecad_lcd_send_command(LCD_ENTRYMODESET | cur_display_control); | |
} | |
// This will 'left justify' text from the cursor | |
void pifacecad_lcd_autoscroll_off(void) | |
{ | |
cur_display_control &= 0xff ^ LCD_ENTRYSHIFTINCREMENT; | |
pifacecad_lcd_send_command(LCD_ENTRYMODESET | cur_display_control); | |
} | |
void pifacecad_lcd_write_custom_bitmap(uint8_t location) | |
{ | |
pifacecad_lcd_send_command(LCD_SETDDRAMADDR | cur_address); | |
pifacecad_lcd_send_data(location); | |
cur_address++; | |
} | |
void pifacecad_lcd_store_custom_bitmap(uint8_t location, uint8_t bitmap[]) | |
{ | |
location &= 0x7; // we only have 8 locations 0-7 | |
pifacecad_lcd_send_command(LCD_SETCGRAMADDR | (location << 3)); | |
int i; | |
for (i = 0; i < 8; i++) { | |
pifacecad_lcd_send_data(bitmap[i]); | |
} | |
} | |
void pifacecad_lcd_send_command(uint8_t command) | |
{ | |
microReset(); | |
while(is_busy()) microPrint(0, 0); // wait until not busy | |
microPrint("before pifacecad_lcd_send_command(", (unsigned)command); | |
pifacecad_lcd_set_rs(0); | |
pifacecad_lcd_send_byte(command); | |
sleep_ns(DELAY_SETTLE_NS); | |
} | |
void pifacecad_lcd_send_data(uint8_t data) | |
{ | |
microReset(); | |
while(is_busy()) microPrint(0, 0); // wait until not busy | |
microPrint("before pifacecad_lcd_send_data(", (unsigned)data); | |
pifacecad_lcd_set_rs(1); | |
pifacecad_lcd_send_byte(data); | |
sleep_ns(DELAY_SETTLE_NS); | |
} | |
void pifacecad_lcd_send_byte(uint8_t b) | |
{ | |
// get current lcd port state and clear the data bits | |
uint8_t current_state = mcp23s17_read_reg(LCD_PORT, hw_addr, mcp23s17_fd); | |
current_state &= 0xF0; // clear the data bits | |
// send first nibble (0bXXXX0000) | |
uint8_t new_byte = current_state | ((b >> 4) & 0xF); // set nibble | |
mcp23s17_write_reg(new_byte, LCD_PORT, hw_addr, mcp23s17_fd); | |
pifacecad_lcd_pulse_enable(); | |
// send second nibble (0b0000XXXX) | |
new_byte = current_state | (b & 0xF); // set nibble | |
mcp23s17_write_reg(new_byte, LCD_PORT, hw_addr, mcp23s17_fd); | |
pifacecad_lcd_pulse_enable(); | |
} | |
void pifacecad_lcd_set_rs(uint8_t state) | |
{ | |
mcp23s17_write_bit(state, PIN_RS, LCD_PORT, hw_addr, mcp23s17_fd); | |
} | |
void pifacecad_lcd_set_rw(uint8_t state) | |
{ | |
mcp23s17_write_bit(state, PIN_RW, LCD_PORT, hw_addr, mcp23s17_fd); | |
} | |
void pifacecad_lcd_set_enable(uint8_t state) | |
{ | |
mcp23s17_write_bit(state, PIN_ENABLE, LCD_PORT, hw_addr, mcp23s17_fd); | |
} | |
void pifacecad_lcd_set_backlight(uint8_t state) | |
{ | |
mcp23s17_write_bit(state, PIN_BACKLIGHT, LCD_PORT, hw_addr, mcp23s17_fd); | |
} | |
/* pulse the enable pin */ | |
void pifacecad_lcd_pulse_enable(void) | |
{ | |
pifacecad_lcd_set_enable(1); | |
sleep_ns(DELAY_PULSE_NS); | |
pifacecad_lcd_set_enable(0); | |
sleep_ns(DELAY_PULSE_NS); | |
} | |
uint8_t colrow2address(uint8_t col, uint8_t row) | |
{ | |
return col + ROW_OFFSETS[row]; | |
} | |
uint8_t address2col(uint8_t address) | |
{ | |
return address % ROW_OFFSETS[1]; | |
} | |
uint8_t address2row(uint8_t address) | |
{ | |
return address > ROW_OFFSETS[1] ? 1 : 0; | |
} | |
static void sleep_ns(long nanoseconds) | |
{ | |
struct timespec time0, time1; | |
time0.tv_sec = 0; | |
time0.tv_nsec = nanoseconds; | |
nanosleep(&time0 , &time1); | |
} | |
static int max(int a, int b) | |
{ | |
return a > b ? a : b; | |
} | |
static int min(int a, int b) | |
{ | |
return a < b ? a : b; | |
} | |
static uint8_t is_busy(void) | |
{ | |
// set data lines as inputs | |
mcp23s17_write_reg(0x0f, IODIRB, hw_addr, mcp23s17_fd); | |
// set RS=0, RW=1 | |
// 2 read, 2 write | |
// pifacecad_lcd_set_rs(0); // instruction register | |
// pifacecad_lcd_set_rw(1); // read | |
// 1 read, 1 write - this is faster | |
// could do without read if I stored the backlight state locally | |
// which is probably the right way of doing things | |
uint8_t reg = mcp23s17_read_reg(LCD_PORT, hw_addr, mcp23s17_fd); | |
reg &= 0xff ^ (1 << PIN_RS); // clear RS | |
reg |= 1 << PIN_RW; // set RW | |
reg &= 0xf0; // clear data | |
mcp23s17_write_reg(reg, LCD_PORT, hw_addr, mcp23s17_fd); | |
// pifacecad_lcd_set_enable(1); | |
reg |= 1 << PIN_ENABLE; // set ENABLE | |
mcp23s17_write_reg(reg, LCD_PORT, hw_addr, mcp23s17_fd); | |
sleep_ns(DELAY_PULSE_NS); | |
// read busy and three most significant bits of address counter | |
// Busy flag is bit 3 | |
reg = mcp23s17_read_reg(LCD_PORT, hw_addr, mcp23s17_fd); | |
// pifacecad_lcd_set_enable(0); | |
reg &= 0xff ^ (1 << PIN_ENABLE); // clear ENABLE | |
mcp23s17_write_reg(reg, LCD_PORT, hw_addr, mcp23s17_fd); | |
sleep_ns(DELAY_PULSE_NS); | |
// lower nibble of address counter | |
// pifacecad_lcd_set_enable(1); | |
reg |= 1 << PIN_ENABLE; // set ENABLE | |
mcp23s17_write_reg(reg, LCD_PORT, hw_addr, mcp23s17_fd); | |
sleep_ns(DELAY_PULSE_NS); | |
// pifacecad_lcd_set_enable(0); | |
// pifacecad_lcd_set_rw(0); | |
reg &= 0xff ^ (1 << PIN_ENABLE); // clear ENABLE | |
reg &= 0xff ^ (1 << PIN_RW); // clear RW | |
mcp23s17_write_reg(reg, LCD_PORT, hw_addr, mcp23s17_fd); | |
sleep_ns(DELAY_PULSE_NS); | |
// set data lines to outputs again | |
mcp23s17_write_reg(0x00, IODIRB, hw_addr, mcp23s17_fd); | |
return (reg & 0xf) >> 3; // return the busy flag | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******************************************************************** | |
* | |
* @file showTimingError.c | |
* @brief Test calls from libpifacecad library for controlling PiFace Control and Display. | |
* | |
* Show text corruptions and other errors for pifacecad.c | |
* | |
* There is no delay after the pifacecad_lcd_clear() and | |
* pifacecad_lcd_home() command other than the 40 us after | |
* each command. | |
* | |
* According to the HITACHI spec for theHD44780U page 24 | |
* 'Clear display' shows a blank in the column execution time. | |
* 'Return home' shows 1.52 ms in the column execution time. | |
* All other commands show 37 us in the column execution time. | |
* | |
* 'Return home' seems to work Ok with or without an extra delay. | |
* | |
* 'Clear display', although not showing an execution time, seems | |
* to require the 1.52 ms shown in the next row, which makes sense, | |
* because this command must sequentially clear each byte of the display. | |
* | |
* Actual measurements using the Busy Flag confirmed that the actual | |
* execution time is somewhere between 1.72 ms and 2.58 ms. This confirms | |
* that the execution time of 'Clear display' should have been 1.52 ms | |
* in the HITACHI spec. It is probably a misprint, because the next line | |
* 'Return home' was measures to execute under 860 us. The extra 200 us | |
* measured is probably experimental error. | |
* | |
* There are text corruptions for delays in the range 100 .. 750 us, | |
* with a peak when the delay is in the range of 300 .. 500 us. | |
* Strangely a delay of 0 or a delay < 100 us shows no text corruptions. | |
* This was the way pifacecad.c is distibuted showing good text displays. | |
* | |
* But pifacecad_lcd_display_off() and pifacecad_lcd_display_on() definitely | |
* do NOT work if the delay after pifacecad_lcd_clear() is < 100 us. | |
* | |
* Suggestion: modify pifacecad_lcd_clear() as follows: | |
* | |
* void pifacecad_lcd_clear(void) | |
* { | |
* pifacecad_lcd_send_command(LCD_CLEARDISPLAY); | |
* sleep_ns(2600000L); // 2.6 ms delay to bridge execution of clear command | |
* cur_address = 0; // this will not slow down displays significantly | |
* } | |
* | |
* Similarly for piface_lcd_home() just in case, to be compiant with spec. | |
* | |
* Author: John E. Wulff, Bowen Mt, Australia | |
* | |
* Copyright (C) 2014 John E Wulff <immediateC@gmail.com> | |
* | |
* This program is free software: you can redistribute it and/or modify | |
* it under the terms of the GNU General Public License as published by | |
* the Free Software Foundation, either version 3 of the License, or | |
* (at your option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |
* | |
* compile and link this program in libpifacecad path like test.c | |
* | |
*******************************************************************/ | |
#include <stdio.h> | |
#include <time.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include "pifacecad.h" | |
char * texts[10] = { | |
"Hello, World!", | |
"00000000011111111112222222222333333333341234567890123456789012345678901234567890", | |
"John E Wulff; author of the iC language\nimmediateC@gmail.com", | |
"OzBerryPi Users Group, Level 2, 66 Oxford St\nDarlinghurst 2010 NSW Australia", | |
"texts[4]", | |
"texts[5]", | |
"texts[6]", | |
"texts[7]", | |
"texts[8]", | |
"Screw you guys\nI'm going home", | |
}; | |
uint8_t bitmap[8] = {0x10, 0x8, 0x7, 0xf, 0xf, 0xe, 0x0, 0x0}; | |
static void sleep_ns(long nanoseconds) | |
{ | |
struct timespec time0, time1; | |
time0.tv_sec = 0; | |
time0.tv_nsec = nanoseconds; | |
nanosleep(&time0 , &time1); | |
} | |
int main(int argc, char ** argv) | |
{ | |
long delay; | |
int n; | |
int p; | |
int d = 0; | |
if (--argc > 0) { | |
if (**++argv == '-') { | |
d = 1; /* use lcd_home() */ | |
(*argv)++; | |
} | |
delay = atol(*argv) * 1000L; | |
} else { | |
printf(" %s <delay>\n", *argv); | |
printf(" enter action on the keyboard\n"); | |
printf(" each action is preceded by lcd_clear()\n"); | |
printf(" and a delay of <delay> us\n"); | |
printf(" negative delay uses lcd_home() with abs(<delay>)\n"); | |
printf(" 0-9 select 10 different texts\n"); | |
printf(" o display on\n"); | |
printf(" p display off\n"); | |
printf(" B Backlight on\n"); | |
printf(" N Backlight off\n"); | |
printf(" b blink on\n"); | |
printf(" n blink off\n"); | |
printf(" c cursor on\n"); | |
printf(" v cursor off\n"); | |
printf(" a set cursor to 5, 1\n"); | |
printf(" l left to right\n"); | |
printf(" r right to left\n"); | |
printf(" m custom bitmap\n"); | |
printf(" Text display is corrupted for delays between 100 and 750 us\n"); | |
printf(" Some actions do not work for delays less than 750 us\n"); | |
printf(" in particular display_on/off (o/p) do not work for delay == 0\n"); | |
printf(" Using lcd_home instead of lcd_clear (-ve delay) causes no errors\n"); | |
printf(" According to HITACHI spec a delay of 1520 us is appropriate\n"); | |
exit(-1); | |
} | |
pifacecad_open(); | |
pifacecad_lcd_cursor_off(); | |
pifacecad_lcd_blink_off(); | |
pifacecad_lcd_backlight_on(); | |
pifacecad_lcd_display_on(); | |
pifacecad_lcd_write(texts[0]); | |
while ((n = getchar()) != 'q') { | |
if (n != '\n') { | |
if (!d) pifacecad_lcd_clear(); else pifacecad_lcd_home(); | |
if (delay) sleep_ns(delay); | |
switch (n) { | |
case '0': | |
case '1': | |
case '2': | |
case '3': | |
case '4': | |
case '5': | |
case '6': | |
case '7': | |
case '8': | |
case '9': | |
p = n -= '0'; | |
pifacecad_lcd_write(texts[n]); | |
printf("texts[%d] \"%s\"; %s + %ld ns\n", n, texts[n], d ? "home" : "clear", delay); | |
break; | |
case 'o': | |
pifacecad_lcd_display_on(); | |
pifacecad_lcd_write(texts[p]); | |
printf("display_on; %s + %ld ns\n", d ? "home" : "clear", delay); | |
break; | |
case 'p': | |
pifacecad_lcd_display_off(); | |
pifacecad_lcd_write(texts[p]); | |
printf("display_off; %s + %ld ns\n", d ? "home" : "clear", delay); | |
break; | |
case 'B': | |
pifacecad_lcd_backlight_on(); | |
pifacecad_lcd_write(texts[p]); | |
printf("Backlight on; %s + %ld ns\n", d ? "home" : "clear", delay); | |
break; | |
case 'N': | |
pifacecad_lcd_backlight_off(); | |
pifacecad_lcd_write(texts[p]); | |
printf("Backlight off; %s + %ld ns\n", d ? "home" : "clear", delay); | |
break; | |
case 'b': | |
pifacecad_lcd_blink_on(); | |
printf("blink on; %s + %ld ns\n", d ? "home" : "clear", delay); | |
break; | |
case 'n': | |
pifacecad_lcd_blink_off(); | |
printf("blink off; %s + %ld ns\n", d ? "home" : "clear", delay); | |
break; | |
case 'c': | |
pifacecad_lcd_cursor_on(); | |
printf("cursor on; %s + %ld ns\n", d ? "home" : "clear", delay); | |
break; | |
case 'v': | |
pifacecad_lcd_cursor_off(); | |
printf("cursor off; %s + %ld ns\n", d ? "home" : "clear", delay); | |
break; | |
case 'a': | |
pifacecad_lcd_set_cursor(5, 1); | |
printf("set cursor to 5, 1; %s + %ld ns\n", d ? "home" : "clear", delay); | |
break; | |
case 'l': | |
pifacecad_lcd_left_to_right(); | |
pifacecad_lcd_write("left 2 right"); | |
printf("left to right; %s + %ld ns\n", d ? "home" : "clear", delay); | |
break; | |
case 'r': | |
pifacecad_lcd_set_cursor(15, 1); | |
pifacecad_lcd_right_to_left(); | |
pifacecad_lcd_write("right 2 left"); | |
printf("right to left; %s + %ld ns\n", d ? "home" : "clear", delay); | |
break; | |
case 'm': | |
pifacecad_lcd_store_custom_bitmap(0, bitmap); | |
pifacecad_lcd_write_custom_bitmap(0); | |
printf("custom bitmap; %s + %ld ns\n", d ? "home" : "clear", delay); | |
break; | |
default: | |
printf("leave the display cleared\n"); | |
break; | |
} | |
sleep_ns(500000000L); /* show sequentially */ | |
} | |
} | |
pifacecad_lcd_blink_off(); | |
pifacecad_lcd_cursor_off(); | |
pifacecad_lcd_display_off(); | |
pifacecad_lcd_backlight_off(); | |
pifacecad_lcd_clear(); | |
pifacecad_close(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment