You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
291 lines
7.8 KiB
291 lines
7.8 KiB
/* |
|
|
|
u8x8_d_bitmap.c |
|
|
|
a bitmap device |
|
|
|
*/ |
|
|
|
#include "stdlib.h" /* malloc */ |
|
#include "stdint.h" /* uint16_t */ |
|
#include "string.h" /* memcpy */ |
|
#include "stdio.h" /* FILE */ |
|
#include "u8g2.h" /* because of u8g2_Setup... */ |
|
|
|
/*========================================================*/ |
|
/* bitmap struct */ |
|
|
|
struct _u8x8_bitmap_struct |
|
{ |
|
u8x8_msg_cb u8x8_bitmap_display_old_cb; |
|
uint16_t tile_width; |
|
uint16_t tile_height; |
|
uint16_t pixel_width; |
|
uint16_t pixel_height; |
|
uint8_t *u8x8_buf; |
|
uint8_t *u8g2_buf; |
|
}; |
|
|
|
typedef struct _u8x8_bitmap_struct u8x8_bitmap_t; |
|
|
|
/*========================================================*/ |
|
/* bitmap functions */ |
|
|
|
uint8_t u8x8_bitmap_SetSize(u8x8_bitmap_t *b, uint16_t pixel_width, uint16_t pixel_height) |
|
{ |
|
if ( b->u8x8_buf != NULL ) |
|
free(b->u8x8_buf); |
|
|
|
b->tile_width = (pixel_width+7)/8; |
|
b->tile_height = (pixel_height+7)/8; |
|
b->pixel_width = pixel_width; |
|
b->pixel_height = pixel_height; |
|
|
|
/* allocate the bitmap twice, one for u8x8 and another bitmap for u8g2 */ |
|
/* however, the final bitmap will always be in the first half of the buffer */ |
|
b->u8x8_buf = (uint8_t *)malloc((size_t)b->tile_width*(size_t)b->tile_height*(size_t)8*(size_t)2); |
|
b->u8g2_buf = b->u8x8_buf+(size_t)b->tile_width*(size_t)b->tile_height*(size_t)8; |
|
|
|
if ( b->u8x8_buf == NULL ) { |
|
b->u8g2_buf = NULL; |
|
return 0; |
|
} |
|
//printf("pixel size: %d %d\n", b->pixel_width, b->pixel_height); |
|
//printf("tile size: %d %d\n", b->tile_width, b->tile_height); |
|
return 1; |
|
} |
|
|
|
void u8x8_bitmap_DrawTiles(u8x8_bitmap_t *b, uint16_t tx, uint16_t ty, uint8_t tile_cnt, uint8_t *tile_ptr) |
|
{ |
|
uint8_t *dest_ptr = b->u8x8_buf; |
|
//printf("tile pos: %d %d, cnt=%d\n", tx, ty, tile_cnt); |
|
if ( dest_ptr == NULL ) |
|
return; |
|
dest_ptr += ty*b->pixel_width; |
|
dest_ptr += tx*8; |
|
memcpy(dest_ptr, tile_ptr, tile_cnt*8); |
|
} |
|
|
|
uint8_t u8x8_bitmap_GetPixel(u8x8_bitmap_t *b, uint16_t x, uint16_t y) |
|
{ |
|
uint8_t *dest_ptr = b->u8x8_buf; |
|
if ( dest_ptr == NULL ) |
|
return 0; |
|
dest_ptr += (y/8)*b->pixel_width; |
|
y &= 7; |
|
dest_ptr += x; |
|
if ( (*dest_ptr & (1<<y)) == 0 ) |
|
return 0; |
|
return 1; |
|
} |
|
|
|
static void tga_write_byte(FILE *fp, uint8_t byte) |
|
{ |
|
fputc(byte, fp); |
|
} |
|
|
|
static void tga_write_word(FILE *fp, uint16_t word) |
|
{ |
|
tga_write_byte(fp, word&255); |
|
tga_write_byte(fp, word>>8); |
|
} |
|
|
|
void u8x8_bitmap_SaveTGA(u8x8_bitmap_t *b, const char *name) |
|
{ |
|
FILE *fp; |
|
uint16_t x, y; |
|
|
|
fp = fopen(name, "wb"); |
|
if ( fp != NULL ) |
|
{ |
|
tga_write_byte(fp, 0); /* no ID */ |
|
tga_write_byte(fp, 0); /* no color map */ |
|
tga_write_byte(fp, 2); /* uncompressed true color */ |
|
tga_write_word(fp, 0); |
|
tga_write_word(fp, 0); |
|
tga_write_byte(fp, 0); |
|
tga_write_word(fp, 0); /* x origin */ |
|
tga_write_word(fp, 0); /* y origin */ |
|
tga_write_word(fp, b->pixel_width); /* width */ |
|
tga_write_word(fp, b->pixel_height); /* height */ |
|
tga_write_byte(fp, 24); /* color depth */ |
|
tga_write_byte(fp, 0); |
|
for( y = 0; y < b->pixel_height; y++ ) |
|
{ |
|
for( x = 0; x < b->pixel_width; x++ ) |
|
{ |
|
if ( u8x8_bitmap_GetPixel(b, x, b->pixel_height-y-1) == 0 ) |
|
{ |
|
tga_write_byte(fp, 255); /* R */ |
|
tga_write_byte(fp, 255); /* G */ |
|
tga_write_byte(fp, 255); /* B */ |
|
} |
|
else |
|
{ |
|
tga_write_byte(fp, 0); /* R */ |
|
tga_write_byte(fp, 0); /* G */ |
|
tga_write_byte(fp, 0); /* B */ |
|
} |
|
} |
|
} |
|
tga_write_word(fp, 0); |
|
tga_write_word(fp, 0); |
|
tga_write_word(fp, 0); |
|
tga_write_word(fp, 0); |
|
fwrite("TRUEVISION-XFILE.", 18, 1, fp); |
|
fclose(fp); |
|
} |
|
} |
|
|
|
|
|
/*========================================================*/ |
|
/* global objects for the bitmap */ |
|
|
|
u8x8_bitmap_t u8x8_bitmap; |
|
|
|
|
|
static u8x8_display_info_t u8x8_bitmap_info = |
|
{ |
|
/* chip_enable_level = */ 0, |
|
/* chip_disable_level = */ 1, |
|
|
|
/* post_chip_enable_wait_ns = */ 0, |
|
/* pre_chip_disable_wait_ns = */ 0, |
|
/* reset_pulse_width_ms = */ 0, |
|
/* post_reset_wait_ms = */ 0, |
|
/* sda_setup_time_ns = */ 0, |
|
/* sck_pulse_width_ns = */ 0, |
|
/* sck_clock_hz = */ 4000000UL, |
|
/* spi_mode = */ 1, |
|
/* i2c_bus_clock_100kHz = */ 0, |
|
/* data_setup_time_ns = */ 0, |
|
/* write_pulse_width_ns = */ 0, |
|
/* tile_width = */ 8, /* dummy value */ |
|
/* tile_hight = */ 4, /* dummy value */ |
|
/* default_x_offset = */ 0, |
|
/* flipmode_x_offset = */ 0, |
|
/* pixel_width = */ 64, /* dummy value */ |
|
/* pixel_height = */ 32 /* dummy value */ |
|
}; |
|
|
|
|
|
/*========================================================*/ |
|
/* functions for handling of the global objects */ |
|
|
|
/* allocate bitmap */ |
|
/* will be called by u8x8_SetupBitmap or u8g2_SetupBitmap */ |
|
static uint8_t u8x8_SetBitmapDeviceSize(u8x8_t *u8x8, uint16_t pixel_width, uint16_t pixel_height) |
|
{ |
|
/* update the global bitmap object, allocate the bitmap */ |
|
if ( u8x8_bitmap_SetSize(&u8x8_bitmap, pixel_width, pixel_height) == 0 ) |
|
return 0; |
|
|
|
/* update the u8x8 object */ |
|
u8x8_bitmap_info.tile_width = (pixel_width+7)/8; |
|
u8x8_bitmap_info.tile_height = (pixel_height+7)/8; |
|
u8x8_bitmap_info.pixel_width = pixel_width; |
|
u8x8_bitmap_info.pixel_height = pixel_height; |
|
return 1; |
|
} |
|
|
|
/* draw tiles to the bitmap, called by the device procedure */ |
|
static void u8x8_DrawBitmapTiles(u8x8_t *u8x8, uint16_t tx, uint16_t ty, uint8_t tile_cnt, uint8_t *tile_ptr) |
|
{ |
|
u8x8_bitmap_DrawTiles(&u8x8_bitmap, tx, ty, tile_cnt, tile_ptr); |
|
} |
|
|
|
uint8_t u8x8_GetBitmapPixel(u8x8_t *u8x8, uint16_t x, uint16_t y) |
|
{ |
|
return u8x8_bitmap_GetPixel(&u8x8_bitmap, x, y); |
|
} |
|
|
|
void u8x8_SaveBitmapTGA(u8x8_t *u8x8, const char *filename) |
|
{ |
|
u8x8_bitmap_SaveTGA(&u8x8_bitmap, filename); |
|
} |
|
|
|
/*========================================================*/ |
|
|
|
static uint8_t u8x8_d_bitmap(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) |
|
{ |
|
u8g2_uint_t x, y, c; |
|
uint8_t *ptr; |
|
switch(msg) |
|
{ |
|
case U8X8_MSG_DISPLAY_SETUP_MEMORY: |
|
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_bitmap_info); |
|
break; |
|
case U8X8_MSG_DISPLAY_INIT: |
|
u8x8_d_helper_display_init(u8x8); /* update low level interfaces (not required here) */ |
|
break; |
|
case U8X8_MSG_DISPLAY_SET_POWER_SAVE: |
|
break; |
|
case U8X8_MSG_DISPLAY_SET_FLIP_MODE: |
|
break; |
|
case U8X8_MSG_DISPLAY_DRAW_TILE: |
|
x = ((u8x8_tile_t *)arg_ptr)->x_pos; |
|
y = ((u8x8_tile_t *)arg_ptr)->y_pos; |
|
c = ((u8x8_tile_t *)arg_ptr)->cnt; |
|
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr; |
|
do |
|
{ |
|
u8x8_DrawBitmapTiles(u8x8, x, y, c, ptr); |
|
x += c; |
|
arg_int--; |
|
} while( arg_int > 0 ); |
|
|
|
break; |
|
default: |
|
return 0; |
|
} |
|
return 1; |
|
} |
|
|
|
|
|
/*========================================================*/ |
|
/* u8x8 and u8g2 setup functions */ |
|
|
|
void u8x8_SetupBitmap(u8x8_t *u8x8, uint16_t pixel_width, uint16_t pixel_height) |
|
{ |
|
u8x8_SetBitmapDeviceSize(u8x8, pixel_width, pixel_height); |
|
|
|
/* setup defaults */ |
|
u8x8_SetupDefaults(u8x8); |
|
|
|
/* setup specific callbacks */ |
|
u8x8->display_cb = u8x8_d_bitmap; |
|
|
|
/* setup display info */ |
|
u8x8_SetupMemory(u8x8); |
|
} |
|
|
|
void u8g2_SetupBitmap(u8g2_t *u8g2, const u8g2_cb_t *u8g2_cb, uint16_t pixel_width, uint16_t pixel_height) |
|
{ |
|
/* allocate bitmap, assign the device callback to u8x8 */ |
|
u8x8_SetupBitmap(u8g2_GetU8x8(u8g2), pixel_width, pixel_height); |
|
|
|
/* configure u8g2 in full buffer mode */ |
|
u8g2_SetupBuffer(u8g2, u8x8_bitmap.u8g2_buf, (pixel_height+7)/8, u8g2_ll_hvline_vertical_top_lsb, u8g2_cb); |
|
} |
|
|
|
|
|
/*========================================================*/ |
|
|
|
|
|
static uint8_t u8x8_d_bitmap_chain(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) |
|
{ |
|
if ( msg == U8X8_MSG_DISPLAY_DRAW_TILE ) |
|
u8x8_d_bitmap(u8x8, msg, arg_int, arg_ptr); |
|
return u8x8_bitmap.u8x8_bitmap_display_old_cb(u8x8, msg, arg_int, arg_ptr); |
|
} |
|
|
|
/* connect the bitmap to an existing u8g2 or u8x8 object */ |
|
uint8_t u8x8_ConnectBitmapToU8x8(u8x8_t *u8x8) |
|
{ |
|
if ( u8x8_SetBitmapDeviceSize(u8x8, u8x8_GetCols(u8x8)*8, u8x8_GetRows(u8x8)*8) == 0 ) |
|
return 0; |
|
u8x8_bitmap.u8x8_bitmap_display_old_cb = u8x8->display_cb; |
|
u8x8->display_cb = u8x8_d_bitmap_chain; |
|
return 1; |
|
} |
|
|
|
|