lw35-upgrade/display/userspace-driver/main.c
2018-04-30 09:08:47 +02:00

177 lines
3.3 KiB
C
Executable File

#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
static void pabort(const char *s)
{
perror(s);
abort();
}
// LCM(bits) = 1440 to be even on a row boundary
// => Blocksize 180 bytes, 3 rows
#define MINBLK 180
#define BLKMUL 4
#define PLSIZE (MINBLK*BLKMUL + 3)
#define ROWSPERBLOCK (3 * BLKMUL)
#define BLKCNT (128 / ROWSPERBLOCK) + 1
int get_addr(int x, int y)
{
int byteno;
byteno = (y * 480 + x) / 8;
if (x % 8 || byteno % 9) {
printf("ERROR: Invalid get_addr offset. Must be on 9 byte boundary.\n");
return -1;
}
byteno -= byteno / 9;
printf("addr = %d\n", byteno);
return byteno;
}
// Row must be multiple of 3
static void transfer(int fd, uint8_t *memory)
{
int ret;
uint8_t *tx;
//uint8_t *rx;
int i;
int txlen;
int addr;
int blk;
txlen = PLSIZE;
//tx = malloc(txlen * sizeof(uint8_t));
//rx = malloc(PLSIZE * sizeof(uint8_t));
tx = memory;
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)NULL,
.len = txlen,
.delay_usecs = 10,
.speed_hz = 0,
.bits_per_word = 0,
};
for (blk = 0; blk < BLKCNT; ++blk) {
printf("tx = %d\n", tx - memory);
addr = get_addr(0, blk * ROWSPERBLOCK);
tx[0] = 0x00; // Opcode: 0
tx[1] = (addr >> 8) & 0xFF; // Base addr:
tx[2] = addr & 0xFF;
tr.tx_buf = (unsigned long)tx; // TODO
tr.len = txlen;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret == 1)
pabort("can't send spi message");
tx += ROWSPERBLOCK * (480/8);
}
/*
for (ret = 0; ret < PLSIZE; ret++) {
if (!(ret % 6))
puts("");
printf("%.2X ", rx[ret]);
}
puts("");
*/
//free(tx);
//free(rx);
}
int main(int argc, char *argv[])
{
int fd;
int ret;
int i;
char temp;
static uint8_t mode = 0;
static uint8_t bits = 8;
static uint32_t speed = 2000000;
uint8_t memory[480*128/8 + 3];
uint8_t *image = memory + 3;
for (i = 0; i < 0; i++) {
printf("%3d: %d\n", i, get_addr(i, 0));
if ((i+1)%8 == 0) {
printf("\n");
}
}
fd = open("/dev/spidev0.0", O_RDWR);
if (fd < 0)
pabort("can't open device");
/*
* spi mode
*/
ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
if (ret == -1)
pabort("can't set spi mode");
ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
if (ret == -1)
pabort("can't get spi mode");
/*
* bits per word
*/
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret == -1)
pabort("can't set bits per word");
ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1)
pabort("can't get bits per word");
/*
* max speed hz
*/
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret == -1)
pabort("can't set max speed hz");
ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if (ret == -1)
pabort("can't get max speed hz");
//printf("spi mode: %d\n", mode);
//printf("bits per word: %d\n", bits);
//printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
for (i = 3; i < ARRAY_SIZE(memory); i++) {
memory[i] = i*8/480;
fread(&temp, 1,1, stdin);
if (i < 720+3)
memory[i] = 0xAA;
else if (i < 720*2+3)
memory[i] = 0xFF;
else
memory[i] = 0x55;
memory[i] = temp;
//rx[i] = 0;
}
transfer(fd, memory);
close(fd);
}