2023-11-07 14:05:51 +00:00
|
|
|
#include <errno.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <linux/i2c-dev.h>
|
|
|
|
#include <i2c/smbus.h>
|
|
|
|
#include <getopt.h>
|
|
|
|
|
|
|
|
//Device specific information. (Perhaps better as command options or config file)
|
|
|
|
#define MPC9808_BUS "/dev/i2c-2"
|
|
|
|
#define DISPLAY_RGB_ADDR 0x62
|
|
|
|
#define DISPLAY_TEXT_ADDR 0x3e
|
|
|
|
|
|
|
|
void init_display(int file) {
|
|
|
|
// Function set 0010 1000 // 2 line mode and 5x8
|
|
|
|
i2c_smbus_write_byte_data(file, 0x00, 0x28);
|
|
|
|
// Display on/off control 0000 1110 // Diplay on; cursor off; blink off
|
|
|
|
i2c_smbus_write_byte_data(file, 0x00, 0x0C);
|
|
|
|
// Clear display
|
|
|
|
i2c_smbus_write_byte_data(file, 0x00, 0x01);
|
|
|
|
i2c_smbus_write_byte_data(file, 0x00, 0x06);
|
|
|
|
|
|
|
|
i2c_smbus_write_byte_data(file, 0x00, 0x02);
|
|
|
|
i2c_smbus_write_byte_data(file, 0x00, 0x84);
|
|
|
|
}
|
|
|
|
|
|
|
|
void clear_display(int file) {
|
|
|
|
i2c_smbus_write_byte_data(file, 0x00, 0x01);
|
|
|
|
}
|
|
|
|
|
|
|
|
void write_to_display_xy(int file, int x, int y, char* message) {
|
|
|
|
int line;
|
|
|
|
if(x > 16) {
|
|
|
|
fprintf(stderr, "Invalid line position");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(y == 1)
|
|
|
|
line = 0x80; // first line (1000 0000 to 1000 1111 possible on 16 characters line) = 0x80 to 0x8f
|
|
|
|
else if(y == 2)
|
|
|
|
line = 0xC0; // second line (1100 0000 to 1100 1111 possible on 16 characters line) = 0xC0 to 0xCf
|
|
|
|
else {
|
|
|
|
fprintf(stderr, "Invalid line position");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
line += x-1;
|
|
|
|
|
|
|
|
i2c_smbus_write_byte_data(file, 0x00, line);
|
|
|
|
while (*message != 0) {
|
|
|
|
i2c_smbus_write_byte_data(file, 0x40, *message);
|
|
|
|
message++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int i2c_init(char *bus, unsigned int address) {
|
|
|
|
int file;
|
|
|
|
|
|
|
|
file = open(bus, O_RDWR);
|
|
|
|
if (file < 0) { // If error
|
|
|
|
fprintf(stderr, "ERROR: opening %s - %s\n", bus, strerror(errno));
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ioctl(file, I2C_SLAVE, address) == -1 ) { // If error
|
|
|
|
fprintf(stderr, "ERROR: setting address %d on i2c bus %s with ioctl() - %s", address, bus, strerror(errno) );
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
return(file);
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_backlight(int r, int g, int b) {
|
|
|
|
int file;
|
|
|
|
file = i2c_init(MPC9808_BUS, DISPLAY_RGB_ADDR);
|
|
|
|
i2c_smbus_write_byte_data(file, 0, 0);
|
|
|
|
i2c_smbus_write_byte_data(file, 1, 0);
|
|
|
|
i2c_smbus_write_byte_data(file, 0x08,0xaa);
|
|
|
|
|
|
|
|
i2c_smbus_write_byte_data(file, 4, r);
|
|
|
|
i2c_smbus_write_byte_data(file, 3, g);
|
|
|
|
i2c_smbus_write_byte_data(file, 2, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char *argv[]) {
|
2023-11-09 13:29:55 +00:00
|
|
|
int l1_x = 1;
|
|
|
|
char *l1_message = NULL;
|
|
|
|
int l2_x = 1;
|
|
|
|
char *l2_message = NULL;
|
|
|
|
int r = 1;
|
|
|
|
int g = 0;
|
|
|
|
int b = 0;
|
2023-11-07 14:05:51 +00:00
|
|
|
|
2023-11-09 13:29:55 +00:00
|
|
|
static struct option long_options[] = {
|
|
|
|
{"x1", required_argument, 0, 'x'},
|
|
|
|
{"m1", required_argument, 0, 'm'},
|
|
|
|
{"x2", required_argument, 0, 'X'},
|
|
|
|
{"m2", required_argument, 0, 'M'},
|
|
|
|
{"r", required_argument, 0, 'r'},
|
|
|
|
{"g", required_argument, 0, 'g'},
|
|
|
|
{"b", required_argument, 0, 'b'},
|
|
|
|
{0, 0, 0, 0} // Terminating entry
|
|
|
|
};
|
|
|
|
|
|
|
|
int option_index = 0;
|
|
|
|
int c;
|
|
|
|
|
|
|
|
while ((c = getopt_long(argc, argv, "x:m:X:M:r:g:b:", long_options, &option_index)) != -1) {
|
|
|
|
switch (c) {
|
|
|
|
case 'x':
|
|
|
|
l1_x = atoi(optarg);
|
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
l1_message = optarg;
|
|
|
|
break;
|
|
|
|
case 'X':
|
|
|
|
l2_x = atoi(optarg);
|
|
|
|
break;
|
|
|
|
case 'M':
|
|
|
|
l2_message = optarg;
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
r = atoi(optarg);
|
|
|
|
break;
|
|
|
|
case 'g':
|
|
|
|
g = atoi(optarg);
|
|
|
|
break;
|
|
|
|
case 'b':
|
|
|
|
b = atoi(optarg);
|
|
|
|
break;
|
|
|
|
case '?': //unregnoniced inputs or missing args
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
fprintf(stderr, "Usage: %s --x1 <value> --x1_message <value>\n", argv[0]);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
break;
|
2023-11-07 14:05:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int file;
|
2023-11-09 13:29:55 +00:00
|
|
|
set_backlight(r, g, b);
|
2023-11-07 14:05:51 +00:00
|
|
|
file = i2c_init(MPC9808_BUS, DISPLAY_TEXT_ADDR);
|
|
|
|
init_display(file);
|
2023-11-09 13:29:55 +00:00
|
|
|
if (l1_message != 0) {
|
|
|
|
write_to_display_xy(file, l1_x, 1, l1_message);
|
|
|
|
}
|
|
|
|
if (l2_message != 0) {
|
|
|
|
write_to_display_xy(file, l2_x, 2, l2_message);
|
|
|
|
}
|
2023-11-07 14:05:51 +00:00
|
|
|
return 0;
|
|
|
|
}
|