|
|
/*------------------------------------------------------------------------------
|
|
|
-- This file is a part of the libuc, microcontroler library
|
|
|
-- Copyright (C) 2013, Alexis Jeandet
|
|
|
--
|
|
|
-- This program is free software; you can redistribute it and/or modify
|
|
|
-- it under the terms of the GNU General Public License as published by
|
|
|
-- the Free Software Foundation; either version 3 of the License, or
|
|
|
-- (at your option) any later version.
|
|
|
--
|
|
|
-- This program is distributed in the hope that it will be useful,
|
|
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
-- GNU General Public License for more details.
|
|
|
--
|
|
|
-- You should have received a copy of the GNU General Public License
|
|
|
-- along with this program; if not, write to the Free Software
|
|
|
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
-------------------------------------------------------------------------------
|
|
|
-- Author : Alexis Jeandet
|
|
|
-- Mail : alexis.jeandet@member.fsf.org
|
|
|
-------------------------------------------------------------------------------*/
|
|
|
|
|
|
#include <SDL.h>
|
|
|
#include <malloc.h>
|
|
|
#include <SDLCD.h>
|
|
|
|
|
|
SDL_Surface *screen;
|
|
|
SDL_Overlay *bmp;
|
|
|
|
|
|
int SDLCD_Xpos=0;
|
|
|
int SDLCD_Ypos=0;
|
|
|
int SDLCD_XWinStrt=0;
|
|
|
int SDLCD_YWinStrt=0;
|
|
|
int SDLCD_XWinEnd=0;
|
|
|
int SDLCD_YWinEnd=0;
|
|
|
|
|
|
void* SDLCD_buffer;
|
|
|
int SDLCD_bpp;
|
|
|
void SDLCD_putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel);
|
|
|
|
|
|
static Uint32 sdl_refresh_timer(Uint32 interval, void *opaque) {
|
|
|
|
|
|
if ( SDL_MUSTLOCK(screen) ) {
|
|
|
if ( SDL_LockSurface(screen) < 0 ) {
|
|
|
fprintf(stderr, "Can’t lock screen: %s\n", SDL_GetError());
|
|
|
return interval;
|
|
|
}
|
|
|
}
|
|
|
//SDL_UpdateRect(screen, 0, 0, screen->w, screen->h);
|
|
|
SDL_Flip(screen);
|
|
|
if ( SDL_MUSTLOCK(screen) ) {
|
|
|
SDL_UnlockSurface(screen);
|
|
|
}
|
|
|
return interval; /* 0 means stop timer */
|
|
|
}
|
|
|
|
|
|
void SDLCD_mkscreen(int resx,int resy,int bpp,int lcdtype)
|
|
|
{
|
|
|
int i=0;
|
|
|
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER)) {
|
|
|
fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
|
|
|
exit(1);
|
|
|
}
|
|
|
screen = SDL_SetVideoMode(resx, resy, bpp, SDL_DOUBLEBUF);
|
|
|
if(!screen) {
|
|
|
fprintf(stderr, "SDL: could not set video mode - exiting\n");
|
|
|
exit(1);
|
|
|
}
|
|
|
if ( SDL_MUSTLOCK(screen) ) {
|
|
|
if ( SDL_LockSurface(screen) < 0 ) {
|
|
|
fprintf(stderr, "Can’t lock screen: %s\n", SDL_GetError());
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
SDL_UpdateRect(screen, 0, 0, resx, resy);
|
|
|
if ( SDL_MUSTLOCK(screen) ) {
|
|
|
SDL_UnlockSurface(screen);
|
|
|
}
|
|
|
SDLCD_buffer = malloc(resx*resy*bpp/8);
|
|
|
SDLCD_bpp = bpp;
|
|
|
for(i=0;i<(resx*resy);i++)
|
|
|
{
|
|
|
SDLCD_putpixel(screen, i%resx, (i/resx), 0xFFFF);
|
|
|
}
|
|
|
SDL_AddTimer(10, sdl_refresh_timer, NULL);
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int SDLCD_init()
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
void SDLCD_writereg(uint32_t reg,uint32_t data)
|
|
|
{
|
|
|
switch (reg) {
|
|
|
case ILI9328_REGISTER_HORIZONTALGRAMADDRESSSET:
|
|
|
if((data>=screen->w) || (data<0))
|
|
|
printf("Warning printing out of bounds HORIZONTALGRAMADDRESSSET=%d",data);
|
|
|
SDLCD_Xpos = data;
|
|
|
break;
|
|
|
case ILI9328_REGISTER_VERTICALGRAMADDRESSSET:
|
|
|
if((data>=screen->h) || (data<0))
|
|
|
printf("Warning printing out of bounds ILI9328_REGISTER_VERTICALGRAMADDRESSSET=%d",data);
|
|
|
SDLCD_Ypos = data;
|
|
|
break;
|
|
|
case ILI9328_REGISTER_HORIZONTALADDRESSSTARTPOSITION:
|
|
|
if((data>=screen->w) || (data<0))
|
|
|
printf("Warning printing out of bounds ILI9328_REGISTER_HORIZONTALADDRESSSTARTPOSITION=%d",data);
|
|
|
SDLCD_XWinStrt = data;
|
|
|
break;
|
|
|
case ILI9328_REGISTER_HORIZONTALADDRESSENDPOSITION:
|
|
|
if((data>=screen->w) || (data<0))
|
|
|
printf("Warning printing out of bounds ILI9328_REGISTER_HORIZONTALADDRESSENDPOSITION=%d",data);
|
|
|
SDLCD_XWinEnd = data;
|
|
|
break;
|
|
|
case ILI9328_REGISTER_VERTICALADDRESSSTARTPOSITION:
|
|
|
if((data>=screen->h) || (data<0))
|
|
|
printf("Warning printing out of bounds ILI9328_REGISTER_VERTICALADDRESSSTARTPOSITION=%d",data);
|
|
|
SDLCD_YWinStrt = data;
|
|
|
break;
|
|
|
case ILI9328_REGISTER_VERTICALADDRESSENDPOSITION:
|
|
|
if((data>=screen->h) || (data<0))
|
|
|
printf("Warning printing out of bounds ILI9328_REGISTER_VERTICALADDRESSENDPOSITION=%d",data);
|
|
|
SDLCD_YWinEnd = data;
|
|
|
break;
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
uint32_t SDLCD_readreg(uint32_t reg)
|
|
|
{
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
|
|
|
void SDLCD_putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
|
|
|
{
|
|
|
int bpp = surface->format->BytesPerPixel;
|
|
|
/* Here p is the address to the pixel we want to set */
|
|
|
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
|
|
|
switch(bpp) {
|
|
|
case 1:
|
|
|
*p = pixel;
|
|
|
break;
|
|
|
case 2:
|
|
|
*(Uint16 *)p = pixel;
|
|
|
break;
|
|
|
case 3:
|
|
|
if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
|
|
|
p[0] = (pixel >> 16) & 0xff;
|
|
|
p[1] = (pixel >> 8) & 0xff;
|
|
|
p[2] = pixel & 0xff;
|
|
|
} else {
|
|
|
p[0] = pixel & 0xff;
|
|
|
p[1] = (pixel >> 8) & 0xff;
|
|
|
p[2] = (pixel >> 16) & 0xff;
|
|
|
}
|
|
|
break;
|
|
|
case 4:
|
|
|
*(Uint32 *)p = pixel;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void SDLCD_putpixel_16bpp(SDL_Surface *surface, int x, int y, Uint32 pixel)
|
|
|
{
|
|
|
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * surface->format->BytesPerPixel;
|
|
|
*(Uint16 *)p = pixel;
|
|
|
}
|
|
|
|
|
|
Uint32 SDLCD_getpixel_16bpp(SDL_Surface *surface, int x, int y)
|
|
|
{
|
|
|
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * surface->format->BytesPerPixel;
|
|
|
return *(Uint16 *)p;
|
|
|
}
|
|
|
|
|
|
Uint32 SDLCD_getpixel(SDL_Surface *surface, int x, int y)
|
|
|
{
|
|
|
int bpp = surface->format->BytesPerPixel;
|
|
|
/* Here p is the address to the pixel we want to retrieve */
|
|
|
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
|
|
|
switch(bpp) {
|
|
|
case 1:
|
|
|
return *p;
|
|
|
case 2:
|
|
|
return *(Uint16 *)p;
|
|
|
case 3:
|
|
|
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
|
|
|
return p[0] << 16 | p[1] << 8 | p[2];
|
|
|
else
|
|
|
return p[0] | p[1] << 8 | p[2] << 16;
|
|
|
case 4:
|
|
|
return *(Uint32 *)p;
|
|
|
default:
|
|
|
return 0;
|
|
|
}
|
|
|
/* shouldn’t happen, but avoids warnings */
|
|
|
}
|
|
|
|
|
|
void SDLCD_writeGRAM(void* buffer,uint32_t count)
|
|
|
{
|
|
|
int i=0;
|
|
|
u_int16_t* ptr=(u_int16_t*)SDLCD_buffer;
|
|
|
u_int16_t* inptr=(u_int16_t*)buffer;
|
|
|
if ( SDL_MUSTLOCK(screen) ) {
|
|
|
if ( SDL_LockSurface(screen) < 0 ) {
|
|
|
fprintf(stderr, "Can’t lock screen: %s\n", SDL_GetError());
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
for(i=0;i<count;i++)
|
|
|
{
|
|
|
SDLCD_putpixel_16bpp(screen,SDLCD_Xpos,SDLCD_Ypos,inptr[i]);
|
|
|
SDLCD_Xpos+=1;
|
|
|
ptr[i]=inptr[i];
|
|
|
if(SDLCD_Xpos>=SDLCD_XWinEnd)
|
|
|
{
|
|
|
SDLCD_Xpos=SDLCD_XWinStrt;
|
|
|
SDLCD_Ypos+=1;
|
|
|
}
|
|
|
if(SDLCD_Ypos>=SDLCD_YWinEnd)
|
|
|
{
|
|
|
SDLCD_Ypos=SDLCD_YWinStrt;
|
|
|
}
|
|
|
}
|
|
|
if ( SDL_MUSTLOCK(screen) ) {
|
|
|
SDL_UnlockSurface(screen);
|
|
|
}
|
|
|
// SDL_UpdateRect(screen, SDLCD_XWinStrt, SDLCD_YWinStrt, SDLCD_XWinEnd-SDLCD_XWinStrt, SDLCD_YWinEnd-SDLCD_YWinStrt);
|
|
|
//SDL_UpdateRect(screen, 0, 0, screen->w, screen->h);
|
|
|
}
|
|
|
|
|
|
void SDLCD_writeGRAM_16bpp(void* buffer,uint32_t count)
|
|
|
{
|
|
|
int i=0;
|
|
|
u_int16_t* inptr=(u_int16_t*)buffer;
|
|
|
if ( SDL_MUSTLOCK(screen) ) {
|
|
|
if ( SDL_LockSurface(screen) < 0 ) {
|
|
|
fprintf(stderr, "Can’t lock screen: %s\n", SDL_GetError());
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
for(i=0;i<count;i++)
|
|
|
{
|
|
|
*(( Uint16 * ) screen->pixels + SDLCD_Ypos * screen->pitch / 2 + SDLCD_Xpos)=inptr[i];
|
|
|
SDLCD_Xpos+=1;
|
|
|
if(SDLCD_Xpos>=SDLCD_XWinEnd)
|
|
|
{
|
|
|
SDLCD_Xpos=SDLCD_XWinStrt;
|
|
|
SDLCD_Ypos+=1;
|
|
|
}
|
|
|
if(SDLCD_Ypos>=SDLCD_YWinEnd)
|
|
|
{
|
|
|
SDLCD_Ypos=SDLCD_YWinStrt;
|
|
|
}
|
|
|
}
|
|
|
if ( SDL_MUSTLOCK(screen) ) {
|
|
|
SDL_UnlockSurface(screen);
|
|
|
}
|
|
|
// SDL_UpdateRect(screen, SDLCD_XWinStrt, SDLCD_YWinStrt, SDLCD_XWinEnd-SDLCD_XWinStrt, SDLCD_YWinEnd-SDLCD_YWinStrt);
|
|
|
//SDL_UpdateRect(screen, 0, 0, screen->w, screen->h);
|
|
|
}
|
|
|
|
|
|
void SDLCD_readGRAM_16bpp(void* buffer,uint32_t count)
|
|
|
{
|
|
|
int i=0;
|
|
|
u_int16_t* ptr=(u_int16_t*)SDLCD_buffer;
|
|
|
u_int16_t* inptr=(u_int16_t*)buffer;
|
|
|
for(i=0;i<count;i++)
|
|
|
{
|
|
|
inptr[i]=*(( Uint16 * ) screen->pixels + SDLCD_Ypos * screen->pitch / 2 + SDLCD_Xpos);
|
|
|
SDLCD_Xpos+=1;
|
|
|
ptr[i]=inptr[i];
|
|
|
if(SDLCD_Xpos>=SDLCD_XWinEnd)
|
|
|
{
|
|
|
SDLCD_Xpos=SDLCD_XWinStrt;
|
|
|
SDLCD_Ypos+=1;
|
|
|
}
|
|
|
if(SDLCD_Ypos>=SDLCD_YWinEnd)
|
|
|
{
|
|
|
SDLCD_Ypos=SDLCD_YWinStrt;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
void SDLCD_readGRAM(void* buffer,uint32_t count)
|
|
|
{
|
|
|
int i=0;
|
|
|
u_int16_t* ptr=(u_int16_t*)SDLCD_buffer;
|
|
|
u_int16_t* inptr=(u_int16_t*)buffer;
|
|
|
for(i=0;i<count;i++)
|
|
|
{
|
|
|
inptr[i]=SDLCD_getpixel_16bpp(screen,SDLCD_Xpos,SDLCD_Ypos);
|
|
|
SDLCD_Xpos+=1;
|
|
|
ptr[i]=inptr[i];
|
|
|
if(SDLCD_Xpos>=SDLCD_XWinEnd)
|
|
|
{
|
|
|
SDLCD_Xpos=SDLCD_XWinStrt;
|
|
|
SDLCD_Ypos+=1;
|
|
|
}
|
|
|
if(SDLCD_Ypos>=SDLCD_YWinEnd)
|
|
|
{
|
|
|
SDLCD_Ypos=SDLCD_YWinStrt;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|