version 1.1, 2018/04/24 16:48:59
|
version 1.1.1.3, 2018/04/24 17:25:10
|
Line 10
|
Line 10
|
/* The controller can support a variety of different displays, but we only |
/* The controller can support a variety of different displays, but we only |
implement one. Most of the commends relating to brightness and geometry |
implement one. Most of the commends relating to brightness and geometry |
setup are ignored. */ |
setup are ignored. */ |
#include "hw.h" |
#include "ssi.h" |
#include "devices.h" |
|
#include "console.h" |
#include "console.h" |
|
|
//#define DEBUG_SSD0323 1 |
//#define DEBUG_SSD0323 1 |
|
|
#ifdef DEBUG_SSD0323 |
#ifdef DEBUG_SSD0323 |
#define DPRINTF(fmt, args...) \ |
#define DPRINTF(fmt, ...) \ |
do { printf("ssd0323: " fmt , ##args); } while (0) |
do { printf("ssd0323: " fmt , ## __VA_ARGS__); } while (0) |
#define BADF(fmt, args...) \ |
#define BADF(fmt, ...) \ |
do { fprintf(stderr, "ssd0323: error: " fmt , ##args); exit(1);} while (0) |
do { fprintf(stderr, "ssd0323: error: " fmt , ## __VA_ARGS__); exit(1);} while (0) |
#else |
#else |
#define DPRINTF(fmt, args...) do {} while(0) |
#define DPRINTF(fmt, ...) do {} while(0) |
#define BADF(fmt, args...) \ |
#define BADF(fmt, ...) \ |
do { fprintf(stderr, "ssd0323: error: " fmt , ##args);} while (0) |
do { fprintf(stderr, "ssd0323: error: " fmt , ## __VA_ARGS__);} while (0) |
#endif |
#endif |
|
|
/* Scaling factor for pixels. */ |
/* Scaling factor for pixels. */ |
Line 43 enum ssd0323_mode
|
Line 42 enum ssd0323_mode
|
}; |
}; |
|
|
typedef struct { |
typedef struct { |
|
SSISlave ssidev; |
DisplayState *ds; |
DisplayState *ds; |
|
|
int cmd_len; |
int cmd_len; |
Line 60 typedef struct {
|
Line 60 typedef struct {
|
uint8_t framebuffer[128 * 80 / 2]; |
uint8_t framebuffer[128 * 80 / 2]; |
} ssd0323_state; |
} ssd0323_state; |
|
|
int ssd0323_xfer_ssi(void *opaque, int data) |
static uint32_t ssd0323_transfer(SSISlave *dev, uint32_t data) |
{ |
{ |
ssd0323_state *s = (ssd0323_state *)opaque; |
ssd0323_state *s = FROM_SSI_SLAVE(ssd0323_state, dev); |
|
|
switch (s->mode) { |
switch (s->mode) { |
case SSD0323_DATA: |
case SSD0323_DATA: |
DPRINTF("data 0x%02x\n", data); |
DPRINTF("data 0x%02x\n", data); |
Line 183 static void ssd0323_update_display(void
|
Line 184 static void ssd0323_update_display(void
|
char *p; |
char *p; |
int dest_width; |
int dest_width; |
|
|
if (s->redraw) { |
if (!s->redraw) |
switch (s->ds->depth) { |
return; |
case 0: |
|
return; |
switch (ds_get_bits_per_pixel(s->ds)) { |
|
case 0: |
|
return; |
|
case 15: |
|
dest_width = 2; |
|
break; |
|
case 16: |
|
dest_width = 2; |
|
break; |
|
case 24: |
|
dest_width = 3; |
|
break; |
|
case 32: |
|
dest_width = 4; |
|
break; |
|
default: |
|
BADF("Bad color depth\n"); |
|
return; |
|
} |
|
p = colortab; |
|
for (i = 0; i < 16; i++) { |
|
int n; |
|
colors[i] = p; |
|
switch (ds_get_bits_per_pixel(s->ds)) { |
case 15: |
case 15: |
dest_width = 2; |
n = i * 2 + (i >> 3); |
|
p[0] = n | (n << 5); |
|
p[1] = (n << 2) | (n >> 3); |
break; |
break; |
case 16: |
case 16: |
dest_width = 2; |
n = i * 2 + (i >> 3); |
|
p[0] = n | (n << 6) | ((n << 1) & 0x20); |
|
p[1] = (n << 3) | (n >> 2); |
break; |
break; |
case 24: |
case 24: |
dest_width = 3; |
|
break; |
|
case 32: |
case 32: |
dest_width = 4; |
n = (i << 4) | i; |
|
p[0] = p[1] = p[2] = n; |
break; |
break; |
default: |
default: |
BADF("Bad color depth\n"); |
BADF("Bad color depth\n"); |
return; |
return; |
} |
} |
p = colortab; |
p += dest_width; |
for (i = 0; i < 16; i++) { |
} |
int n; |
/* TODO: Implement row/column remapping. */ |
colors[i] = p; |
dest = ds_get_data(s->ds); |
switch (s->ds->depth) { |
for (y = 0; y < 64; y++) { |
case 15: |
line = y; |
n = i * 2 + (i >> 3); |
src = s->framebuffer + 64 * line; |
p[0] = n | (n << 5); |
for (x = 0; x < 64; x++) { |
p[1] = (n << 2) | (n >> 3); |
int val; |
break; |
val = *src >> 4; |
case 16: |
for (i = 0; i < MAGNIFY; i++) { |
n = i * 2 + (i >> 3); |
memcpy(dest, colors[val], dest_width); |
p[0] = n | (n << 6) | ((n << 1) & 0x20); |
dest += dest_width; |
p[1] = (n << 3) | (n >> 2); |
|
break; |
|
case 24: |
|
case 32: |
|
n = (i << 4) | i; |
|
p[0] = p[1] = p[2] = n; |
|
break; |
|
default: |
|
BADF("Bad color depth\n"); |
|
return; |
|
} |
|
p += dest_width; |
|
} |
|
/* TODO: Implement row/column remapping. */ |
|
dest = s->ds->data; |
|
for (y = 0; y < 64; y++) { |
|
line = y; |
|
src = s->framebuffer + 64 * line; |
|
for (x = 0; x < 64; x++) { |
|
int val; |
|
val = *src >> 4; |
|
for (i = 0; i < MAGNIFY; i++) { |
|
memcpy(dest, colors[val], dest_width); |
|
dest += dest_width; |
|
} |
|
val = *src & 0xf; |
|
for (i = 0; i < MAGNIFY; i++) { |
|
memcpy(dest, colors[val], dest_width); |
|
dest += dest_width; |
|
} |
|
src++; |
|
} |
} |
for (i = 1; i < MAGNIFY; i++) { |
val = *src & 0xf; |
memcpy(dest, dest - dest_width * MAGNIFY * 128, |
for (i = 0; i < MAGNIFY; i++) { |
dest_width * 128 * MAGNIFY); |
memcpy(dest, colors[val], dest_width); |
dest += dest_width * 128 * MAGNIFY; |
dest += dest_width; |
} |
} |
|
src++; |
|
} |
|
for (i = 1; i < MAGNIFY; i++) { |
|
memcpy(dest, dest - dest_width * MAGNIFY * 128, |
|
dest_width * 128 * MAGNIFY); |
|
dest += dest_width * 128 * MAGNIFY; |
} |
} |
} |
} |
|
s->redraw = 0; |
dpy_update(s->ds, 0, 0, 128 * MAGNIFY, 64 * MAGNIFY); |
dpy_update(s->ds, 0, 0, 128 * MAGNIFY, 64 * MAGNIFY); |
} |
} |
|
|
Line 272 static void ssd0323_cd(void *opaque, int
|
Line 275 static void ssd0323_cd(void *opaque, int
|
s->mode = level ? SSD0323_DATA : SSD0323_CMD; |
s->mode = level ? SSD0323_DATA : SSD0323_CMD; |
} |
} |
|
|
void *ssd0323_init(DisplayState *ds, qemu_irq *cmd_p) |
static void ssd0323_save(QEMUFile *f, void *opaque) |
{ |
{ |
ssd0323_state *s; |
ssd0323_state *s = (ssd0323_state *)opaque; |
qemu_irq *cmd; |
int i; |
|
|
|
qemu_put_be32(f, s->cmd_len); |
|
qemu_put_be32(f, s->cmd); |
|
for (i = 0; i < 8; i++) |
|
qemu_put_be32(f, s->cmd_data[i]); |
|
qemu_put_be32(f, s->row); |
|
qemu_put_be32(f, s->row_start); |
|
qemu_put_be32(f, s->row_end); |
|
qemu_put_be32(f, s->col); |
|
qemu_put_be32(f, s->col_start); |
|
qemu_put_be32(f, s->col_end); |
|
qemu_put_be32(f, s->redraw); |
|
qemu_put_be32(f, s->remap); |
|
qemu_put_be32(f, s->mode); |
|
qemu_put_buffer(f, s->framebuffer, sizeof(s->framebuffer)); |
|
} |
|
|
|
static int ssd0323_load(QEMUFile *f, void *opaque, int version_id) |
|
{ |
|
ssd0323_state *s = (ssd0323_state *)opaque; |
|
int i; |
|
|
|
if (version_id != 1) |
|
return -EINVAL; |
|
|
|
s->cmd_len = qemu_get_be32(f); |
|
s->cmd = qemu_get_be32(f); |
|
for (i = 0; i < 8; i++) |
|
s->cmd_data[i] = qemu_get_be32(f); |
|
s->row = qemu_get_be32(f); |
|
s->row_start = qemu_get_be32(f); |
|
s->row_end = qemu_get_be32(f); |
|
s->col = qemu_get_be32(f); |
|
s->col_start = qemu_get_be32(f); |
|
s->col_end = qemu_get_be32(f); |
|
s->redraw = qemu_get_be32(f); |
|
s->remap = qemu_get_be32(f); |
|
s->mode = qemu_get_be32(f); |
|
qemu_get_buffer(f, s->framebuffer, sizeof(s->framebuffer)); |
|
|
|
return 0; |
|
} |
|
|
|
static void ssd0323_init(SSISlave *dev) |
|
{ |
|
ssd0323_state *s = FROM_SSI_SLAVE(ssd0323_state, dev); |
|
|
s = (ssd0323_state *)qemu_mallocz(sizeof(ssd0323_state)); |
|
s->ds = ds; |
|
graphic_console_init(ds, ssd0323_update_display, ssd0323_invalidate_display, |
|
NULL, s); |
|
dpy_resize(s->ds, 128 * MAGNIFY, 64 * MAGNIFY); |
|
s->col_end = 63; |
s->col_end = 63; |
s->row_end = 79; |
s->row_end = 79; |
|
s->ds = graphic_console_init(ssd0323_update_display, |
|
ssd0323_invalidate_display, |
|
NULL, NULL, s); |
|
qemu_console_resize(s->ds, 128 * MAGNIFY, 64 * MAGNIFY); |
|
|
|
qdev_init_gpio_in(&dev->qdev, ssd0323_cd, 1); |
|
|
|
register_savevm("ssd0323_oled", -1, 1, ssd0323_save, ssd0323_load, s); |
|
} |
|
|
cmd = qemu_allocate_irqs(ssd0323_cd, s, 1); |
static SSISlaveInfo ssd0323_info = { |
*cmd_p = *cmd; |
.qdev.name = "ssd0323", |
|
.qdev.size = sizeof(ssd0323_state), |
|
.init = ssd0323_init, |
|
.transfer = ssd0323_transfer |
|
}; |
|
|
return s; |
static void ssd03232_register_devices(void) |
|
{ |
|
ssi_register_slave(&ssd0323_info); |
} |
} |
|
|
|
device_init(ssd03232_register_devices) |