Sprites
authorWintermate <wintermute@hannover.ccc.de>
Mon, 7 Oct 2013 17:21:41 +0000 (19:21 +0200)
committerWintermate <wintermute@hannover.ccc.de>
Mon, 7 Oct 2013 17:21:41 +0000 (19:21 +0200)
Makefile
drivers/fatfs/ffconf.h
lcd/display.c
lcd/display_r0ket.c [deleted file]
lcd/sprite.c [new file with mode: 0644]
lcd/sprite.h [new file with mode: 0644]
main.c

index b1f7810..0685d8b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -172,7 +172,7 @@ OBJS += sysinit.o pwm.o iap.o
 \r
 \r
 VPATH += lcd\r
-OBJS += display.o\r
+OBJS += display.o sprite.o\r
 \r
 VPATH += dataflash\r
 OBJS += at45db041d.o iobase.o diskio.o\r
index 3453ad1..8575532 100644 (file)
 / Function and Buffer Configurations
 /----------------------------------------------------------------------------*/
 
-#define        _FS_TINY        1               /* 0 or 1 */
+#define _FS_TINY        1               /* 0 or 1 */
 /* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system
 /  object instead of the sector buffer in the individual file object for file
 /  data transfer. This reduces memory consumption 512 bytes each file object. */
 
 
-#define _FS_READONLY   CFG_SDCARD_READONLY // 0        /* 0 or 1 */
+#define _FS_READONLY    1 //CFG_SDCARD_READONLY // 0    /* 0 or 1 */
 /* Setting _FS_READONLY to 1 defines read only configuration. This removes
 /  writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename,
 /  f_truncate and useless f_getfree. */
 
 
-#define _FS_MINIMIZE   0       /* 0, 1, 2 or 3 */
+#define _FS_MINIMIZE    1       /* 0, 1, 2 or 3 */
 /* The _FS_MINIMIZE option defines minimization level to remove some functions.
 /
 /   0: Full function.
 /   3: f_lseek is removed in addition to level 2. */
 
 
-#define        _USE_STRFUNC    0       /* 0, 1 or 2 */
+#define _USE_STRFUNC    0       /* 0, 1 or 2 */
 /* To enable string functions, set _USE_STRFUNC to 1 or 2. */
 
 
-#define        _USE_MKFS       0               /* 0 or 1 */
+#define _USE_MKFS       0               /* 0 or 1 */
 /* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */
 
 
-#define        _USE_FORWARD    0       /* 0 or 1 */
+#define _USE_FORWARD    0       /* 0 or 1 */
 /* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */
 
 
@@ -54,7 +54,7 @@
 / Locale and Namespace Configurations
 /----------------------------------------------------------------------------*/
 
-#define _CODE_PAGE     858
+#define _CODE_PAGE      1
 /* The _CODE_PAGE specifies the OEM code page to be used on the target system.
 /  Incorrect setting of the code page can cause a file open failure.
 /
 /   857  - Turkish (OEM)
 /   862  - Hebrew (OEM)
 /   874  - Thai (OEM, Windows)
-/      1    - ASCII only (Valid for non LFN cfg.)
+/       1    - ASCII only (Valid for non LFN cfg.)
 */
 
 
-#define        _USE_LFN        0               /* 0, 1 or 2 */
-#define        _MAX_LFN        64              /* Maximum LFN length to handle (12 to 255) */
+#define _USE_LFN        0               /* 0, 1 or 2 */
+#define _MAX_LFN        255             /* Maximum LFN length to handle (12 to 255) */
 /* The _USE_LFN option switches the LFN support.
 /
 /   0: Disable LFN. _MAX_LFN and _LFN_UNICODE have no effect.
 /  to the project. */
 
 
-#define        _LFN_UNICODE    0       /* 0 or 1 */
+#define _LFN_UNICODE    0       /* 0 or 1 */
 /* To switch the character code set on FatFs API to Unicode,
 /  enable LFN feature and set _LFN_UNICODE to 1.
 */
 
 
-#define _FS_RPATH      0               /* 0 or 1 */
+#define _FS_RPATH       1               /* 0 or 1 */
 /* When _FS_RPATH is set to 1, relative path feature is enabled and f_chdir,
 /  f_chdrive function are available.
 /  Note that output of the f_readdir fnction is affected by this option. */
 / Physical Drive Configurations
 /----------------------------------------------------------------------------*/
 
-#define _DRIVES                1
+#define _DRIVES         1
 /* Number of volumes (logical drives) to be used. */
 
 
-#define        _MAX_SS         512             /* 512, 1024, 2048 or 4096 */
+#define _MAX_SS         512             /* 512, 1024, 2048 or 4096 */
 /* Maximum sector size to be handled.
 /  Always set 512 for memory card and hard disk but a larger value may be
 /  required for floppy disk (512/1024) and optical disk (512/2048).
 /  to the disk_ioctl function. */
 
 
-#define        _MULTI_PARTITION        0       /* 0 or 1 */
+#define _MULTI_PARTITION        0       /* 0 or 1 */
 /* When _MULTI_PARTITION is set to 0, each volume is bound to the same physical
 / drive number and can mount only first primaly partition. When it is set to 1,
 / each volume is tied to the partitions listed in Drives[]. */
 / System Configurations
 /----------------------------------------------------------------------------*/
 
-#define _WORD_ACCESS   0       /* 0 or 1 */
+#define _WORD_ACCESS    1       /* 0 or 1 */
 /* The _WORD_ACCESS option defines which access method is used to the word
 /  data on the FAT volume.
 /
 /  performance and code size. */
 
 
-#define _FS_REENTRANT  0               /* 0 or 1 */
-#define _FS_TIMEOUT            1000    /* Timeout period in unit of time ticks */
-#define        _SYNC_t                 HANDLE  /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */
+#define _FS_REENTRANT   0               /* 0 or 1 */
+#define _FS_TIMEOUT             1000    /* Timeout period in unit of time ticks */
+#define _SYNC_t                 HANDLE  /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */
 /* The _FS_REENTRANT option switches the reentrancy of the FatFs module.
 /
 /   0: Disable reentrancy. _SYNC_t and _FS_TIMEOUT have no effect.
index 4849753..cb91904 100644 (file)
@@ -8,7 +8,20 @@
 
 #include <r0ketports.h>
 
+#ifdef CFG_USBMSC
+#include <core/usbhid-rom/usbmsc.h>
+
+static uint32_t usbintstatus;
+#endif
+
 static void lcd_select() {
+#ifdef CFG_USBMSC
+  if(usbMSCenabled) {
+    usbintstatus = USB_DEVINTEN;
+    USB_DEVINTEN = 0;
+  }
+#endif
+
     /* the LCD requires 9-Bit frames */
   uint32_t configReg = ( SSP_SSP0CR0_DSS_9BIT     // Data size = 9-bit
                          | SSP_SSP0CR0_FRF_SPI    // Frame format = SPI
@@ -24,6 +37,12 @@ static void lcd_deselect() {
                          | SSP_SSP0CR0_FRF_SPI    // Frame format = SPI
                          | SSP_SSP0CR0_SCR_8);    // Serial clock rate = 8
   SSP_SSP0CR0 = configReg;
+
+#ifdef CFG_USBMSC
+  if(usbMSCenabled) {
+    USB_DEVINTEN = usbintstatus;
+  }
+#endif
 }
 
 static inline void lcd_write(uint16_t frame) {
@@ -85,12 +104,12 @@ void badge_display_init(void) {
    * 10: set x address (upper bits): X[6-4] = 0
    */
   static uint8_t const initseq[]= { 0xE2, 0xAF, // Display ON
-                                   //      0xA1,       // Mirror-X
-                                   0xc8, // mirror-y
-                                   0xa7, // invert (1 = black)
-                                   0xA4, 0x2F,
-                                   0xB0, 0x10,
-                                   0x9f, 0x24 };
+                                    //      0xA1,       // Mirror-X
+                                    0xc8, // mirror-y
+                                    0xa7, // invert (1 = black)
+                                    0xA4, 0x2F,
+                                    0xB0, 0x10,
+                                    0x9f, 0x24 };
   for(uint8_t i = 0; i < sizeof(initseq); ++i){
     lcd_write_command(initseq[i]);
     systickDelay(5);
@@ -106,7 +125,7 @@ void badge_framebuffer_flush(badge_framebuffer const *fb) {
   lcd_write_command(0x10);
   lcd_write_command(0x00);
 
-  
+
   for(int i = 0; i < 9 * 96; ++i) {
     lcd_write_data(fb->data[0][i]);
   }
diff --git a/lcd/display_r0ket.c b/lcd/display_r0ket.c
deleted file mode 100644 (file)
index 8d2d29c..0000000
+++ /dev/null
@@ -1,488 +0,0 @@
-#include <string.h>
-
-#include <display.h>
-#include <sysdefs.h>
-#include "lpc134x.h"
-#include "core/ssp/ssp.h"
-#include "gpio/gpio.h"
-#include "basic/basic.h"
-#include "basic/config.h"
-#include "usb/usbmsc.h"
-
-
-#define DISPLAY_N1200 0
-#define DISPLAY_N1600 1
-
-#define MODE 8 /* 8 or 16 */
-
-#if MODE == 8
-#define putpix(x) _helper_pixel8(x)
-#define px_INIT_MODE 2
-#define px_PACK(r,g,b) COLORPACK_RGB332(r,g,b)
-#define px_type uint8_t
-#else
- #if MODE == 12
- #define putpix(x) _helper_pixel12(x)
- #define px_INIT_MODE 3
- #define px_PACK(r,g,b) COLORPACK_RGB444(r,g,b)
- #define px_type uint16_t
- #else
- #define putpix(x) _helper_pixel16(x)
- #define px_INIT_MODE 5
- #define px_PACK(r,g,b) COLORPACK_RGB565(r,g,b)
- #define px_type uint16_t
- #endif
-#endif
-
-/**************************************************************************/
-/* Utility routines to manage nokia display */
-/**************************************************************************/
-
-uint8_t lcdBuffer[RESX*RESY_B];
-uint32_t intstatus; // Caches USB interrupt state
-                    // (need to disable MSC while displaying)
-uint8_t displayType;
-
-#define TYPE_CMD    0
-#define TYPE_DATA   1
-
-static void lcd_select() {
-#if CFG_USBMSC
-    if(usbMSCenabled){
-        intstatus=USB_DEVINTEN;
-        USB_DEVINTEN=0;
-    };
-#endif
-    /* the LCD requires 9-Bit frames */
-    uint32_t configReg = ( SSP_SSP0CR0_DSS_9BIT     // Data size = 9-bit
-                  | SSP_SSP0CR0_FRF_SPI             // Frame format = SPI
-                  | SSP_SSP0CR0_SCR_8);             // Serial clock rate = 8
-    SSP_SSP0CR0 = configReg;
-    gpioSetValue(RB_LCD_CS, 0);
-}
-
-static void lcd_deselect() {
-    gpioSetValue(RB_LCD_CS, 1);
-    /* reset the bus to 8-Bit frames that everyone else uses */
-    uint32_t configReg = ( SSP_SSP0CR0_DSS_8BIT     // Data size = 8-bit
-                  | SSP_SSP0CR0_FRF_SPI             // Frame format = SPI
-                  | SSP_SSP0CR0_SCR_8);             // Serial clock rate = 8
-    SSP_SSP0CR0 = configReg;
-#if CFG_USBMSC
-    if(usbMSCenabled){
-        USB_DEVINTEN=intstatus;
-    };
-#endif
-}
-
-static void lcdWrite(uint8_t cd, uint8_t data) {
-    uint16_t frame = 0x0;
-
-    frame = cd << 8;
-    frame |= data;
-
-    while ((SSP_SSP0SR & (SSP_SSP0SR_TNF_NOTFULL | SSP_SSP0SR_BSY_BUSY)) != SSP_SSP0SR_TNF_NOTFULL);
-    SSP_SSP0DR = frame;
-    while ((SSP_SSP0SR & (SSP_SSP0SR_BSY_BUSY|SSP_SSP0SR_RNE_NOTEMPTY)) != SSP_SSP0SR_RNE_NOTEMPTY);
-    /* clear the FIFO */
-    frame = SSP_SSP0DR;
-}
-
-#define CS 2,1
-#define SCK 2,11
-#define SDA 0,9
-#define RST 2,2
-
-uint8_t lcdRead(uint8_t data)
-{
-    uint32_t op211cache=IOCON_PIO2_11;
-    uint32_t op09cache=IOCON_PIO0_9;
-    uint32_t dircache=GPIO_GPIO2DIR;
-    IOCON_PIO2_11=IOCON_PIO2_11_FUNC_GPIO|IOCON_PIO2_11_MODE_PULLUP;
-    IOCON_PIO0_9=IOCON_PIO0_9_FUNC_GPIO|IOCON_PIO0_9_MODE_PULLUP;
-    gpioSetDir(SCK, 1);
-
-    uint8_t i;
-
-    gpioSetDir(SDA, 1);
-    gpioSetValue(SCK, 0);
-    gpioSetValue(CS, 0);
-    delayms(1);
-
-    gpioSetValue(SDA, 0);
-    gpioSetValue(SCK, 1);
-    delayms(1);
-    
-    for(i=0; i<8; i++){
-        gpioSetValue(SCK, 0);
-        delayms(1);
-        if( data & 0x80 )
-            gpioSetValue(SDA, 1);
-        else
-            gpioSetValue(SDA, 0);
-        data <<= 1;
-        gpioSetValue(SCK, 1);
-        delayms(1);
-    }
-    uint8_t ret = 0;
-
-    gpioSetDir(SDA, 0);
-    for(i=0; i<8; i++){
-        gpioSetValue(SCK, 0);
-        delayms(1);
-        ret <<= 1;
-        ret |= gpioGetValue(SDA);
-        gpioSetValue(SCK, 1);
-        delayms(1);
-    }
-    gpioSetValue(SCK, 0);
-
-    gpioSetValue(CS, 1);
-    gpioSetDir(SDA, 1);
-    IOCON_PIO2_11=op211cache;
-    IOCON_PIO0_9=op09cache;
-    GPIO_GPIO2DIR=dircache;
-    delayms(1);
-    return ret;
-}
-
-
-void lcdInit(void) {
-    int id;
-
-    sspInit(0, sspClockPolarity_Low, sspClockPhase_RisingEdge);
-
-    gpioSetValue(RB_LCD_CS, 1);
-    gpioSetValue(RB_LCD_RST, 1);
-
-    gpioSetDir(RB_LCD_CS, gpioDirection_Output);
-    gpioSetDir(RB_LCD_RST, gpioDirection_Output);
-
-    delayms(100);
-    gpioSetValue(RB_LCD_RST, 0);
-    delayms(100);
-    gpioSetValue(RB_LCD_RST, 1);
-    delayms(100);
-
-    id=lcdRead(220); // ID3
-    
-    if(id==14)
-        displayType=DISPLAY_N1600;
-    else /* ID3 == 48 */
-        displayType=DISPLAY_N1200;
-    
-/* Small Nokia 1200 LCD docs:
- *           clear/ set
- *  on       0xae / 0xaf
- *  invert   0xa6 / 0xa7
- *  mirror-x 0xA0 / 0xA1
- *  mirror-y 0xc7 / 0xc8
- *
- *  0x20+x contrast (0=black - 0x2e)
- *  0x40+x offset in rows from top (-0x7f)
- *  0x80+x contrast? (0=black -0x9f?)
- *  0xd0+x black lines from top? (-0xdf?)
- *
- */
-    lcd_select();
-
-    if(displayType==DISPLAY_N1200){
-       /* Decoded:
-        * E2: Internal reset
-        * AF: Display on/off: DON = 1
-        * A1: undefined?
-        * A4: all on/normal: DAL = 0
-        * 2F: charge pump on/off: PC = 1
-        * B0: set y address: Y[0-3] = 0
-        * 10: set x address (upper bits): X[6-4] = 0
-        */
-        static uint8_t initseq[]= { 0xE2,0xAF, // Display ON
-                             0xA1, // Mirror-X
-                             0xA4, 0x2F, 0xB0, 0x10};
-        int i = 0;
-        while(i<sizeof(initseq)){
-            lcdWrite(TYPE_CMD,initseq[i++]);
-            delayms(5); // actually only needed after the first
-        }
-    }else{ /* displayType==DISPLAY_N1600 */
-        static uint8_t initseq_d[] = {
-                       /* The controller is a PCF8833 -
-                   documentation can be found online.
-                        * CMD 01: Soft-reset
-                        * CMD 11: Sleep-out
-                        * CMD 29: Display ON
-                        * CMD 03: Booster voltage ON
-                        * CMD 13: Normal display mode
-                        * CMD 3A: interface pixel format 
-                        *   DAT 02  | 02:  8 bit/pixel (3:3:2)
-                        *           | 03: 12 bit/pixel (4:4:4)
-                        *           | 05: 16 bit/pixel (5:6:5)
-                        * CMD 2A: column address set
-                        *   DAT 1    : xs
-                        *   DAT 98-2 : xe
-                        * CMD 2B: page address set
-                        *   DAT 1    : ys
-                        *   DAT 70-2 : ye
-                        */
-            0x11, 
-            0x29, 
-            0x03, 
-            0x13, 
-            0x3A, px_INIT_MODE, 
-            0x2A, 1, 98-2, 
-            0x2B, 1, 70-2
-        };
-        uint16_t initseq_c = ~  (  /* comands: 1, data: 0 */
-                (1<<0) |
-                (1<<1) |
-                (1<<2) |
-                (1<<3) |
-                (1<<4) | (0<< 5) |
-                (1<<6) | (0<< 7) | (0<< 8) |
-                (1<<9) | (0<<10) | (0<<11) |
-                0);
-        int i = 0;
-
-        lcdWrite(0, 0x01); /* most color displays need the pause */
-        delayms(10);
-
-        while(i<sizeof(initseq_d)){
-            lcdWrite(initseq_c&1, initseq_d[i++]);
-            initseq_c = initseq_c >> 1;
-        }
-    }
-    lcd_deselect();
-}
-
-void lcdFill(char f){
-    memset(lcdBuffer,f,RESX*RESY_B);
-#if 0
-    int x;
-    for(x=0;x<RESX*RESY_B;x++) {
-        lcdBuffer[x]=f;
-    }
-#endif
-}
-
-void lcdSetPixel(char x, char y, bool f){
-    if (x<0 || x> RESX || y<0 || y > RESY)
-        return;
-    char y_byte = (RESY-(y+1)) / 8;
-    char y_off = (RESY-(y+1)) % 8;
-    char byte = lcdBuffer[y_byte*RESX+(RESX-(x+1))];
-    if (f) {
-        byte |= (1 << y_off);
-    } else {
-        byte &= ~(1 << y_off);
-    }
-    lcdBuffer[y_byte*RESX+(RESX-(x+1))] = byte;
-}
-
-bool lcdGetPixel(char x, char y){
-    char y_byte = (RESY-(y+1)) / 8;
-    char y_off = (RESY-(y+1)) % 8;
-    char byte = lcdBuffer[y_byte*RESX+(RESX-(x+1))];
-    return byte & (1 << y_off);
-}
-
-// Color display helper functions
-static inline void _helper_pixel8(uint8_t color1){
-    lcdWrite(TYPE_DATA, color1);
-}
-
-static void _helper_pixel12(uint16_t color){
-    static char odd=0;
-    static char rest;
-    if(odd){
-        lcdWrite(TYPE_DATA,(rest<<4) | (color>>8));
-        lcdWrite(TYPE_DATA,color&0xff);
-    }else{
-        lcdWrite(TYPE_DATA,(color>>4)&0xff);
-        rest=(color&0x0f);
-    };
-    odd=1-odd;
-}
-
-static void _helper_pixel16(uint16_t color){
-    lcdWrite(TYPE_DATA,color>>8);
-    lcdWrite(TYPE_DATA,color&0xFF);
-}
-
-#define COLORPACK_RGB565(r,g,b) (((r&0xF8) << 8) | ((g&0xFC)<<3) | ((b&0xF8) >> 3))
-#define COLORPACK_RGB444(r,g,b) ( ((r&0xF0)<<4) | (g&0xF0) | ((b&0xF0)>>4) )
-#define COLORPACK_RGB332(r,g,b) ( (((r>>5)&0x7)<<5) | (((g>>5)&0x7)<<2) | ((b>>6)&0x3) )
-
-static const px_type COLOR_FG =   px_PACK(0x00, 0x00, 0x00);
-static const px_type COLOR_BG =   px_PACK(0xff, 0xff, 0xff);
-
-void lcdDisplay(void) {
-    char byte;
-    lcd_select();
-
-    if(displayType==DISPLAY_N1200){
-      lcdWrite(TYPE_CMD,0xB0);
-      lcdWrite(TYPE_CMD,0x10);
-      lcdWrite(TYPE_CMD,0x00);
-      uint16_t i,page;
-      for(page=0; page<RESY_B;page++) {
-          for(i=0; i<RESX; i++) {
-              if (GLOBAL(lcdmirror))
-                  byte=lcdBuffer[page*RESX+RESX-1-(i)];
-              else
-                  byte=lcdBuffer[page*RESX+(i)];
-  
-              if (GLOBAL(lcdinvert))
-                  byte=~byte;
-      
-              lcdWrite(TYPE_DATA,byte);
-          }
-      }
-    } else { /* displayType==DISPLAY_N1600 */
-      uint16_t x,y;
-      bool px;
-      lcdWrite(TYPE_CMD,0x2C);
-  
-      for(y=RESY;y>0;y--){
-          for(x=RESX;x>0;x--){
-              if(GLOBAL(lcdmirror))
-                  px=lcdGetPixel(RESX-x,y-1);
-              else
-                  px=lcdGetPixel(x-1,y-1);
-
-             if((!px)^(!GLOBAL(lcdinvert))) {
-                     putpix(COLOR_FG); /* foreground */
-             } else {
-                     putpix(COLOR_BG); /* background */
-             }
-          }
-      }
-    };
-    lcd_deselect();
-}
-
-void lcdRefresh() __attribute__ ((weak, alias ("lcdDisplay")));
-
-inline void lcdInvert(void) {
-    GLOBAL(lcdinvert)=!GLOBAL(lcdinvert);
-}
-
-void lcdSetContrast(int c) {
-    lcd_select();
-    if(displayType==DISPLAY_N1200){
-        if(c<0x1F)
-            lcdWrite(TYPE_CMD,0x80+c);
-    }else{ /* displayType==DISPLAY_N1600 */
-        if(c<0x40) {
-            lcdWrite(TYPE_CMD,0x25);
-            lcdWrite(TYPE_DATA,4*c);
-        };
-    }
-    lcd_deselect();
-}
-
-void lcdSetInvert(int c) {
-    lcd_select();
-     /* it doesn't harm N1600, save space */
-//  if(displayType==DISPLAY_N1200)
-        lcdWrite(TYPE_CMD,(c&1)+0xa6);
-    lcd_deselect();
-}
-
-/* deprecated */
-void __attribute__((__deprecated__)) lcdToggleFlag(int flag) {
-    if(flag==LCD_MIRRORX)
-        GLOBAL(lcdmirror)=!GLOBAL(lcdmirror);
-    if(flag==LCD_INVERTED)
-        GLOBAL(lcdinvert)=!GLOBAL(lcdinvert);
-}
-
-void lcdShiftH(bool right, bool wrap) {
-       uint8_t tmp;
-       for (int yb = 0; yb<RESY_B; yb++) {
-               if (right) {
-                       tmp = lcdBuffer[yb*RESX];
-                       memmove(lcdBuffer + yb*RESX,lcdBuffer + yb*RESX+1 ,RESX-1);
-            lcdBuffer[yb*RESX+(RESX-1)] = wrap?tmp:0;
-               } else {
-                       tmp = lcdBuffer[yb*RESX+(RESX-1)];
-                       memmove(lcdBuffer + yb*RESX+1,lcdBuffer + yb*RESX ,RESX-1);
-                       lcdBuffer[yb*RESX] = wrap?tmp:0;
-               }
-       }
-}
-
-void lcdShiftV8(bool up, bool wrap) {
-       uint8_t tmp[RESX];
-       if (!up) {
-               if (wrap)
-            memmove(tmp, lcdBuffer, RESX);
-        else
-            memset(tmp,0,RESX);
-               memmove(lcdBuffer,lcdBuffer+RESX ,RESX*(RESY_B-1));
-               memmove(lcdBuffer+RESX*(RESY_B-1),tmp,RESX);
-       } else {
-               if (wrap)
-            memmove(tmp, lcdBuffer+RESX*(RESY_B-1), RESX);
-        else
-            memset(tmp,0,RESX);
-               memmove(lcdBuffer+RESX,lcdBuffer ,RESX*(RESY_B-1));
-               memmove(lcdBuffer,tmp,RESX);
-       }
-}
-
-void lcdShiftV(bool up, bool wrap) {
-       uint8_t tmp[RESX];
-       if (up) {
-               if (wrap) 
-            memmove(tmp,lcdBuffer+((RESY_B-1)*RESX),RESX);
-        else
-            memset(tmp,0,RESX);
-               for (int x = 0; x<RESX; x++){
-                       for (int y = RESY_B-1; y > 0; y--){
-                               lcdBuffer[x+(y*RESX)] = (lcdBuffer[x+(y*RESX)] << 1) |( lcdBuffer[x+((y-1)*RESX)] >> 7);
-                       }
-                       lcdBuffer[x] = ( lcdBuffer[x] << 1) | ((tmp[x]>>3)&1);
-               }
-                               
-       } else {
-               if (wrap)
-            memmove(tmp,lcdBuffer,RESX);
-        else
-            memset(tmp,0,RESX);
-               for (int x = 0; x<RESX; x++){
-                       for (int y = 0; y < (RESY_B-1); y++){
-                               lcdBuffer[x+(y*RESX)] = (lcdBuffer[x+(y*RESX)] >> 1) |( lcdBuffer[x+((y+1)*RESX)] << 7);
-                       }
-                       lcdBuffer[x+((RESY_B-1)*RESX)] = ( lcdBuffer[x+((RESY_B-1)*RESX)] >> 1) | ((tmp[x]<<3)&8);
-               }       
-       }
-}      
-
-void lcdShift(int x, int y, bool wrap) {
-       bool dir=true;
-
-    if(x<0){
-        dir=false;
-        x=-x;
-    };
-
-    while(x-->0)
-        lcdShiftH(dir, wrap);
-
-    if(y<0){
-        dir=false;
-        y=-y;
-    }else{
-        dir=true;
-    };
-
-    while(y>=8){
-        y-=8;
-        lcdShiftV8(dir, wrap);
-    };
-
-    while(y-->0)
-        lcdShiftV(dir, wrap);
-}
-
diff --git a/lcd/sprite.c b/lcd/sprite.c
new file mode 100644 (file)
index 0000000..cb815fc
--- /dev/null
@@ -0,0 +1,117 @@
+#include "sprite.h"
+
+//#include <assert.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdio.h>
+
+typedef struct  {
+  uint8_t const *data_ptr;
+  uint8_t        left_in_byte;
+} sprite_column_iterator;
+
+static inline  int8_t i8min( int8_t x,  int8_t y) { return x < y ? x : y; }
+static inline  int8_t i8max( int8_t x,  int8_t y) { return x < y ? y : x; }
+static inline uint8_t u8min(uint8_t x, uint8_t y) { return x < y ? x : y; }
+static inline uint8_t u8max(uint8_t x, uint8_t y) { return x < y ? y : x; }
+
+static inline sprite_column_iterator sprite_column_iterator_init(badge_sprite const *sprite, uint8_t xskip) {
+  sprite_column_iterator result = { sprite->data, CHAR_BIT };
+
+  if(xskip != 0) {
+    int skip_bits = (xskip * sprite->height);
+
+    result.data_ptr      += skip_bits / CHAR_BIT;
+    result.left_in_byte   = CHAR_BIT - skip_bits % 8;
+  }
+
+  return result;
+}
+
+static inline uint32_t sprite_column_iterator_pop(sprite_column_iterator *iter, uint8_t height) {
+  uint32_t column = 0;
+
+  if(iter->left_in_byte > height) {
+    column = *iter->data_ptr >> (CHAR_BIT - iter->left_in_byte) & ((1 << height) - 1);
+    iter->left_in_byte -= height;
+  } else {
+    column = *iter->data_ptr >> (CHAR_BIT - iter->left_in_byte);
+
+    uint8_t shlen = iter->left_in_byte;
+    uint8_t n;
+
+    for(n = height - shlen; n >= CHAR_BIT; n -= CHAR_BIT) {
+      column |= *++iter->data_ptr << shlen;
+      shlen += CHAR_BIT;
+    }
+
+    column |= (*++iter->data_ptr & ((1 << n) - 1)) << shlen;
+    iter->left_in_byte = CHAR_BIT - n;
+  }
+
+  return column;
+}
+
+void badge_framebuffer_blt(badge_framebuffer *fb,
+                           int8_t x,
+                           int8_t y,
+                           badge_sprite const *sprite,
+                           unsigned flags)
+{
+  if(y >= BADGE_DISPLAY_HEIGHT ||
+     x >= BADGE_DISPLAY_WIDTH  ||
+     y <= -sprite->height ||
+     x <= -sprite->width) {
+    // Nichts zu tun.
+    return;
+  }
+
+  int8_t  y_major = y / BADGE_DISPLAY_STRIPE_HEIGHT - (y < 0);
+  uint8_t y_minor = (uint8_t) (y - y_major * BADGE_DISPLAY_STRIPE_HEIGHT);
+
+  int8_t xmove;
+  int8_t xcursor;
+  int8_t xend;
+  uint8_t xskip;
+
+  if(flags & BADGE_BLT_MIRRORED) {
+    xmove   = -1;
+    xcursor =  i8min(x + sprite->width, BADGE_DISPLAY_WIDTH) - 1;
+    xend    =  i8max(x, 0) - 1;
+    xskip   =  x + sprite->width - xcursor - 1;
+  } else {
+    xmove   =  1;
+    xcursor =  i8max(x, 0);
+    xend    =  i8min(x + sprite->width, BADGE_DISPLAY_WIDTH);
+    xskip   =  xcursor - x;
+  }
+
+  sprite_column_iterator col_iter = sprite_column_iterator_init(sprite, xskip);
+
+  while(xcursor != xend) {
+    uint32_t column = sprite_column_iterator_pop(&col_iter, sprite->height);
+
+/*
+    assert(xcursor >= 0);
+    assert(xcursor < BADGE_DISPLAY_WIDTH);
+*/
+
+    if(y_major >= 0) {
+      fb->data[y_major][xcursor] |= (uint8_t) column << y_minor;
+    }
+
+    uint8_t stripe_max = u8min((sprite->height + y_minor - 1) / BADGE_DISPLAY_STRIPE_HEIGHT,
+                               BADGE_DISPLAY_STRIPE_COUNT - y_major - 1);
+
+    for(uint8_t stripe_ptr = i8max(1, -y_major); stripe_ptr <= stripe_max; ++stripe_ptr) {
+/*
+      assert(y_major + stripe_ptr >= 0);
+      assert(y_major + stripe_ptr < BADGE_DISPLAY_STRIPE_COUNT);
+*/
+
+      fb->data[y_major + stripe_ptr][xcursor] |= (uint8_t) (column >> (stripe_ptr * BADGE_DISPLAY_STRIPE_HEIGHT - y_minor));
+    }
+
+    xcursor += xmove;
+  }
+}
diff --git a/lcd/sprite.h b/lcd/sprite.h
new file mode 100644 (file)
index 0000000..3a3aba8
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef INCLUDED_BADGE2013_MOCKUP_SPRITE_H
+#define INCLUDED_BADGE2013_MOCKUP_SPRITE_H
+
+#include "display.h"
+#include <stdint.h>
+
+enum {
+  BADGE_SPRITE_MAX_WIDTH = 32
+};
+
+typedef struct {
+  uint8_t width;
+  uint8_t height;
+  uint8_t const *data;
+} badge_sprite;
+
+enum {
+  BADGE_BLT_MIRRORED = 1
+};
+
+void badge_framebuffer_blt(badge_framebuffer *fb,
+                           int8_t x,
+                           int8_t y,
+                           badge_sprite const *sprite,
+                           unsigned flags);
+
+#endif
diff --git a/main.c b/main.c
index d0dfce7..4cdd2cc 100644 (file)
--- a/main.c
+++ b/main.c
@@ -1,5 +1,5 @@
 /**************************************************************************/
-/*! 
+/*!
     @file     main.c
     @author   K. Townsend (microBuilder.eu)
 
 #endif
 
 #include "lcd/display.h"
+#include "lcd/sprite.h"
 
 #include "r0ketports.h"
+#include "drivers/fatfs/ff.h"
 
 uint8_t getInputRaw(void) {
     uint8_t result = BTN_NONE;
@@ -100,7 +102,7 @@ void backlightInit(void) {
 
   /* Enable PWM0 */
   TMR_TMR16B1PWMC = TMR_TMR16B1PWMC_PWM0_ENABLED;
+
   // Enable Step-UP
   gpioSetDir(RB_PWR_LCDBL, gpioDirection_Output);
   gpioSetValue(RB_PWR_LCDBL, 0);
@@ -115,14 +117,14 @@ void rbInit() {
     // TODO FIXME more power init needed ? chrg + volt input ?
     // enable external vcc
     gpioSetDir(RB_PWR_GOOD, gpioDirection_Output);
-    gpioSetValue (RB_PWR_GOOD, 0); 
+    gpioSetValue (RB_PWR_GOOD, 0);
 
     // Disable USB Connect (we don't want USB by default)
     gpioSetDir(USB_CONNECT, gpioDirection_Output);
     gpioSetValue(USB_CONNECT, 1);
 
     static uint8_t ports[] = { RB_BTN0, RB_BTN1, RB_BTN2, RB_BTN3, RB_BTN4,
-                        RB_LED0, RB_LED1, RB_LED2, 
+                        RB_LED0, RB_LED1, RB_LED2,
                         RB_SPI_SS0, RB_SPI_SS1, RB_SPI_SS2,
                         RB_SPI_SS3, RB_SPI_SS4, RB_SPI_SS5,
                         RB_HB0, RB_HB1, RB_HB2,
@@ -147,7 +149,7 @@ void rbInit() {
 
     // prepare LEDs
     IOCON_JTAG_TDI_PIO0_11 &= ~IOCON_JTAG_TDI_PIO0_11_FUNC_MASK;
-    IOCON_JTAG_TDI_PIO0_11 |= IOCON_JTAG_TDI_PIO0_11_FUNC_GPIO; 
+    IOCON_JTAG_TDI_PIO0_11 |= IOCON_JTAG_TDI_PIO0_11_FUNC_GPIO;
 
     while( i<16 ){
         gpioSetDir(ports[i],ports[i+1], gpioDirection_Output);
@@ -161,16 +163,16 @@ void rbInit() {
     // prepare lcd
     // TODO FIXME more init needed ?
     gpioSetDir(RB_LCD_BL, gpioDirection_Output);
-    gpioSetValue (RB_LCD_BL, 0); 
+    gpioSetValue (RB_LCD_BL, 0);
 
     // Set P0.0 to GPIO
     RB_PWR_LCDBL_IO&= ~RB_PWR_LCDBL_IO_FUNC_MASK;
-    RB_PWR_LCDBL_IO|= RB_PWR_LCDBL_IO_FUNC_GPIO; 
+    RB_PWR_LCDBL_IO|= RB_PWR_LCDBL_IO_FUNC_GPIO;
     gpioSetDir(RB_PWR_LCDBL, gpioDirection_Input);
     gpioSetPullup(&RB_PWR_LCDBL_IO, gpioPullupMode_Inactive);
 
     // prepare SPI/SS
-    // TODO FIXME init miso/mosi/sck somehow ? 
+    // TODO FIXME init miso/mosi/sck somehow ?
     // prepare hackerbus
     while(i<sizeof(ports)){
         gpioSetDir(ports[i],ports[i+1], gpioDirection_Output);
@@ -184,7 +186,7 @@ void rbInit() {
 
 
 /**************************************************************************/
-/*! 
+/*!
     Main program entry point.  After reset, normal code execution will
     begin here.
 */
@@ -204,74 +206,111 @@ int main(void)
   badge_display_init();
   gpioSetDir(0, 11, gpioDirection_Output);
 
-
-  badge_framebuffer fb = { 
+  badge_framebuffer fb = {
     {
       {
-       1,   2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
-       21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
-       41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
-       61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
-       81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96
+        1,   2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+        21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+        41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+        61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+        81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96
       }, {
-       1,   2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
-       21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
-       41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
-       61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
-       81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96
+        1,   2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+        21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+        41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+        61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+        81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96
       }, {
-       1,   2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
-       21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
-       41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
-       61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
-       81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96
+        1,   2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+        21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+        41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+        61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+        81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96
       }, {
-       1,   2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
-       21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
-       41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
-       61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
-       81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96
+        1,   2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+        21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+        41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+        61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+        81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96
       }, {
-       1,   2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
-       21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
-       41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
-       61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
-       81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96
+        1,   2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+        21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+        41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+        61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+        81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96
       }, {
-       1,   2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
-       21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
-       41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
-       61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
-       81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96
+        1,   2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+        21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+        41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+        61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+        81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96
       }, {
-       1,   2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
-       21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
-       41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
-       61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
-       81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96
+        1,   2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+        21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+        41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+        61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+        81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96
       }, {
-       1,   2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
-       21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
-       41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
-       61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
-       81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96
+        1,   2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+        21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+        41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+        61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+        81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96
       }, {
-       1,   2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
-       21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
-       41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
-       61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
-       81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96
+        1,   2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+        21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+        41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+        61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+        81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96
       }
     }
   };
 
-  badge_framebuffer_flush(&fb);
+  //  badge_framebuffer_flush(&fb);
 
   usbMSCInit();
-  for(;;);
+
+  int res = 0;
+  FATFS fatvol;
+
+  if(FR_OK == f_mount(0, &fatvol)) {
+    FIL fil;
+    if(FR_OK == (res = f_open(&fil, "sshot.dat", FA_OPEN_EXISTING | FA_READ))) {
+      UINT readbytes;
+
+      if(FR_OK != f_read(&fil, &fb, sizeof(fb), &readbytes)) {
+        gpioSetDir(RB_LED3, gpioDirection_Output);
+        gpioSetValue(RB_LED3, 1);
+      }
+
+      f_close(&fil);
+    } else {
+      fb.data[0][0] = res;
+      gpioSetDir(RB_LED1, gpioDirection_Output);
+      gpioSetValue(RB_LED1, 1);
+    }
+  } else {
+    gpioSetDir(RB_LED2, gpioDirection_Output);
+    gpioSetValue(RB_LED2, 1);
+  }
+
+  badge_framebuffer_flush(&fb);
 
   for(uint8_t i = 0; ; ++i) {
     gpioSetValue(0, 11, i & 1);
+
+    uint8_t buttons = getInputRaw();
+    memset(&fb, 0, sizeof(fb));
+
+    badge_sprite const sp = { 4, 4, (uint8_t const *) "\xff\xff" };
+
+    if(buttons & BTN_UP)    { badge_framebuffer_blt(&fb, 30, 10, &sp, 0); }
+    if(buttons & BTN_DOWN)  { badge_framebuffer_blt(&fb, 30, 50, &sp, 0); }
+    if(buttons & BTN_LEFT)  { badge_framebuffer_blt(&fb, 10, 30, &sp, 0); }
+    if(buttons & BTN_RIGHT) { badge_framebuffer_blt(&fb, 50, 30, &sp, 0); }
+
+    badge_framebuffer_flush(&fb);
+
     systickDelay(500);
   }
 
This page took 0.065607 seconds and 4 git commands to generate.