#include #include #include #include #include #include #if 0 #include #include // Require wiringPi library #else #include #include #include #include #endif static void wiringPiSetup(void) { } static int _cs; static int spi_setup(int cs, int bps) { int fd; spi_ioctl_configure_t sic; _cs = cs; sic.sic_addr = cs; sic.sic_mode = 0; sic.sic_speed = bps; fd = open("/dev/spi0", O_RDWR); if (fd >= 0) { if (ioctl(fd, SPI_IOCTL_CONFIGURE, &sic) == -1) { close(fd); fd = -1; } } return fd; } static int spi_write(int fd, unsigned char *buffer, int len) { spi_ioctl_transfer_t sit; sit.sit_addr = _cs; sit.sit_send = buffer; sit.sit_sendlen = len; sit.sit_recv = NULL; sit.sit_recvlen = 0; return ioctl(fd, SPI_IOCTL_TRANSFER, &sit); } enum pinmode { INPUT = GPIO_PIN_INPUT, OUTPUT = GPIO_PIN_OUTPUT }; static void pinMode(int pin, int mode) { } static int digitalRead(int pin) { int fd, val = -1; struct gpio_req gp; fd = open("/dev/gpio0", O_RDWR); if (fd != -1) { gp.gp_name[0] = '\0'; gp.gp_pin = pin; ioctl(fd, GPIOREAD, &gp); val = gp.gp_value; close(fd); } return val; } static int digitalWrite(int pin, int val) { int fd; struct gpio_req gp; fd = open("/dev/gpio0", O_RDWR); if (fd != -1) { gp.gp_name[0] = '\0'; gp.gp_pin = pin; gp.gp_value = val; ioctl(fd, GPIOWRITE, &gp); close(fd); } } #define PNG_DEBUG 3 #include #if 0 /* wiringPi */ #define RESET_PIN 0 /* GPIO17, pin 11 */ #define DC_PIN 6 /* GPIO25, pin 22 */ #define BUSY_PIN 5 /* GPIO24, pin 18 */ #else /* bananaPi */ #define RESET_PIN 1 /* PA1, pin 11 */ #define DC_PIN 2 /* PA2, pin 22 */ #define BUSY_PIN 26 /* PC4, pin 18 */ #endif int fd; int x, y; int width, height; png_byte color_type; png_byte bit_depth; png_structp png_ptr; png_infop info_ptr; int number_of_passes; png_bytep *row_pointers; /* Declear functions */ void abort_(const char *s, ...); void read_png_file(const char *file_name); void process_file(void); void DEPG0213RWS800F13_Wait(void); void DEPG0213RWS800F13_Command(uint8_t cmd); void DEPG0213RWS800F13_Data(uint8_t data); void DEPG0213RWS800F13_Write(uint8_t *buf, int n); void DEPG0213RWS800F13_UpdateAndSleep(void); void DEPG0213RWS800F13_Init(void); void abort_(const char *s, ...) { va_list args; va_start(args, s); vfprintf(stderr, s, args); fprintf(stderr, "\n"); va_end(args); abort(); } void read_png_file(const char *file_name) { char header[8]; // 8 is the maximum size that can be checked /* open file and test for it being a png */ FILE *fp = fopen(file_name, "rb"); if (!fp) abort_("[read_png_file] File %s could not be opened for reading", file_name); fread(header, 1, 8, fp); if (png_sig_cmp(header, 0, 8)) abort_("[read_png_file] File %s is not recognized as a PNG file", file_name); /* initialize stuff */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) abort_("[read_png_file] png_create_read_struct failed"); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) abort_("[read_png_file] png_create_info_struct failed"); if (setjmp(png_jmpbuf(png_ptr))) abort_("[read_png_file] Error during init_io"); png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); png_set_expand(png_ptr); png_read_info(png_ptr, info_ptr); width = png_get_image_width(png_ptr, info_ptr); height = png_get_image_height(png_ptr, info_ptr); color_type = png_get_color_type(png_ptr, info_ptr); bit_depth = png_get_bit_depth(png_ptr, info_ptr); number_of_passes = png_set_interlace_handling(png_ptr); png_read_update_info(png_ptr, info_ptr); /* read file */ if (setjmp(png_jmpbuf(png_ptr))) abort_("[read_png_file] Error during read_image"); row_pointers = (png_bytep *)malloc(sizeof(png_bytep) * height); for (y = 0; y < height; y++) row_pointers[y] = (png_byte *)malloc(png_get_rowbytes(png_ptr, info_ptr)); png_read_image(png_ptr, row_pointers); fclose(fp); } void getrgb(unsigned w, unsigned h, png_byte *rows[], uint8_t rBuf[], uint8_t bBuf[]) { unsigned y, x; uint8_t tmp = 0; for (y = 0; y < h; y++) { png_byte *row = rows[y]; uint16_t r = y; for (x = 0; x < w; x++) { png_byte *ptr = &(row[x * 3]); png_byte red, grn, blu; uint16_t c = x + 6; // start at offset 6 red = ptr[0]; grn = ptr[1]; blu = ptr[2]; // Extract the red color of the drawing board if (red > 100 && grn < 100 && blu < 100) { tmp = rBuf[16 * r + (15 - c / 8)]; rBuf[16 * r + (15 - c / 8)] = tmp | (1 << (c % 8)); } // Extract the black color of the drawing board else if (red + grn + blu > 700) { tmp = bBuf[16 * r + (15 - c / 8)]; bBuf[16 * r + (15 - c / 8)] = tmp | (1 << (c % 8)); } } } } void getgray(unsigned w, unsigned h, png_byte *rows[], uint8_t rBuf[], uint8_t bBuf[]) { unsigned y, x; uint8_t tmp = 0; for (y = 0; y < h; y++) { png_byte *row = rows[y]; uint16_t r = y; for (x = 0; x < w; x++) { png_byte *ptr = &(row[x]); png_byte red, grn, blu; uint16_t c = x + 6; // start at offset 6 red = grn = blu = ptr[0]; // Extract the red color of the drawing board if (red > 100 && grn < 100 && blu < 100) { tmp = rBuf[16 * r + (15 - c / 8)]; rBuf[16 * r + (15 - c / 8)] = tmp | (1 << (c % 8)); } // Extract the black color of the drawing board else if (red + grn + blu > 700) { tmp = bBuf[16 * r + (15 - c / 8)]; bBuf[16 * r + (15 - c / 8)] = tmp | (1 << (c % 8)); } } } } void getplane(unsigned w, unsigned h, png_byte *rows[], uint8_t rBuf[], uint8_t bBuf[]) { unsigned y, x; uint8_t tmp = 0; for (y = 0; y < h; y++) { png_byte *row = rows[y]; uint16_t r = y; for (x = 0; x < w; x++) { png_byte *ptr = &(row[x/8]); png_byte mask = 1 << (7 - (x & 7)); png_byte red, grn, blu; uint16_t c = x + 6; // start at offset 6 red = grn = blu = ptr[0] & mask ? 255 : 0; // Extract the red color of the drawing board if (red > 100 && grn < 100 && blu < 100) { tmp = rBuf[16 * r + (15 - c / 8)]; rBuf[16 * r + (15 - c / 8)] = tmp | (1 << (c % 8)); } // Extract the black color of the drawing board else if (red + grn + blu > 700) { tmp = bBuf[16 * r + (15 - c / 8)]; bBuf[16 * r + (15 - c / 8)] = tmp | (1 << (c % 8)); } } } } void process_file(void) { uint8_t rBuf[4000] = {0x00}; // 250 lines of 128 bits each uint8_t bBuf[4000] = {0x00}; uint16_t w,h; int type, depth; w = width < 122 ? width : 122; h = height < 250 ? height : 250; type = png_get_color_type(png_ptr, info_ptr); depth = png_get_bit_depth(png_ptr, info_ptr); printf("Depth %d\n", depth); switch (type) { case PNG_COLOR_TYPE_GRAY: printf("GRAY\n"); if (depth == 1) /* 1bit black/white */ getplane(w, h, row_pointers, rBuf, bBuf); else if (depth == 8) /* 8bit grayscale */ getgray(w, h, row_pointers, rBuf, bBuf); break; case PNG_COLOR_TYPE_GRAY_ALPHA: printf("GRAY_ALPHA\n"); break; case PNG_COLOR_TYPE_RGB: printf("RGB\n"); if (depth == 8) /* 24bit RGB */ getrgb(w, h, row_pointers, rBuf, bBuf); break; case PNG_COLOR_TYPE_RGB_ALPHA: printf("RGB_ALPHA\n"); break; default: fprintf(stderr,"Not a supported color type\n"); break; } printf("Init\n"); DEPG0213RWS800F13_Init(); printf("Red\n"); DEPG0213RWS800F13_Wait(); DEPG0213RWS800F13_Command(0x26); DEPG0213RWS800F13_Write(rBuf, 4000); printf("Black\n"); DEPG0213RWS800F13_Wait(); DEPG0213RWS800F13_Command(0x24); DEPG0213RWS800F13_Write(bBuf, 4000); printf("Update\n"); DEPG0213RWS800F13_UpdateAndSleep(); } void DEPG0213RWS800F13_Wait(void) { while (1) { if (digitalRead(BUSY_PIN) == 0) break; usleep(5); } usleep(100); } void DEPG0213RWS800F13_Command(uint8_t cmd) { digitalWrite(DC_PIN, 0); spi_write(fd, &cmd, 1); } void DEPG0213RWS800F13_Data(uint8_t data) { digitalWrite(DC_PIN, 1); spi_write(fd, &data, 1); } void DEPG0213RWS800F13_Write(uint8_t *buf, int n) { digitalWrite(DC_PIN, 1); spi_write(fd, buf, n); } void DEPG0213RWS800F13_UpdateAndSleep(void) { DEPG0213RWS800F13_Command(0x20); DEPG0213RWS800F13_Wait(); DEPG0213RWS800F13_Command(0x10); DEPG0213RWS800F13_Data(0x01); usleep(100 * 1000); } void DEPG0213RWS800F13_Init(void) { usleep(10 * 1000); digitalWrite(RESET_PIN, 0); usleep(10 * 1000); digitalWrite(RESET_PIN, 1); usleep(10 * 1000); DEPG0213RWS800F13_Wait(); DEPG0213RWS800F13_Command(0x12); DEPG0213RWS800F13_Wait(); } int main(int argc, char *argv[]) { const char *fn = argc > 1 ? argv[1] : "new.png"; wiringPiSetup(); // DC pinMode(DC_PIN, OUTPUT); // RST pinMode(RESET_PIN, OUTPUT); // BUSY pinMode(BUSY_PIN, INPUT); fd = spi_setup(0, 500000); read_png_file(fn); process_file(); return 0; }