| Index: emcore/trunk/target/ipodnano2g/lcd.c | 
| — | — | @@ -1,397 +1,397 @@ | 
| 2 |  | -//
 | 
| 3 |  | -//
 | 
| 4 |  | -//    Copyright 2010 TheSeven
 | 
| 5 |  | -//
 | 
| 6 |  | -//
 | 
| 7 |  | -//    This file is part of emCORE.
 | 
| 8 |  | -//
 | 
| 9 |  | -//    emCORE is free software: you can redistribute it and/or
 | 
| 10 |  | -//    modify it under the terms of the GNU General Public License as
 | 
| 11 |  | -//    published by the Free Software Foundation, either version 2 of the
 | 
| 12 |  | -//    License, or (at your option) any later version.
 | 
| 13 |  | -//
 | 
| 14 |  | -//    emCORE is distributed in the hope that it will be useful,
 | 
| 15 |  | -//    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
| 16 |  | -//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 | 
| 17 |  | -//    See the GNU General Public License for more details.
 | 
| 18 |  | -//
 | 
| 19 |  | -//    You should have received a copy of the GNU General Public License along
 | 
| 20 |  | -//    with emCORE.  If not, see <http://www.gnu.org/licenses/>.
 | 
| 21 |  | -//
 | 
| 22 |  | -//
 | 
| 23 |  | -
 | 
| 24 |  | -
 | 
| 25 |  | -#include "global.h"
 | 
| 26 |  | -#include "thread.h"
 | 
| 27 |  | -#include "s5l8701.h"
 | 
| 28 |  | -#include "util.h"
 | 
| 29 |  | -
 | 
| 30 |  | -
 | 
| 31 |  | -static struct mutex lcd_mutex IDATA_ATTR;
 | 
| 32 |  | -static struct wakeup lcd_wakeup IDATA_ATTR;
 | 
| 33 |  | -
 | 
| 34 |  | -static bool lcd_dma_busy IDATA_ATTR;
 | 
| 35 |  | -static bool lcd_in_irq IDATA_ATTR;
 | 
| 36 |  | -
 | 
| 37 |  | -
 | 
| 38 |  | -void lcd_init()
 | 
| 39 |  | -{
 | 
| 40 |  | -    mutex_init(&lcd_mutex);
 | 
| 41 |  | -    wakeup_init(&lcd_wakeup);
 | 
| 42 |  | -    DMACON8 = 0x20590000;
 | 
| 43 |  | -    LCDCON = 0xd01;
 | 
| 44 |  | -    LCDPHTIME = 0;
 | 
| 45 |  | -    lcd_in_irq = false;
 | 
| 46 |  | -    lcd_dma_busy = false;
 | 
| 47 |  | -}
 | 
| 48 |  | -
 | 
| 49 |  | -int lcd_get_width()
 | 
| 50 |  | -{
 | 
| 51 |  | -    return LCD_WIDTH;
 | 
| 52 |  | -}
 | 
| 53 |  | -
 | 
| 54 |  | -int lcd_get_height()
 | 
| 55 |  | -{
 | 
| 56 |  | -    return LCD_HEIGHT;
 | 
| 57 |  | -}
 | 
| 58 |  | -
 | 
| 59 |  | -int lcd_get_bytes_per_pixel()
 | 
| 60 |  | -{
 | 
| 61 |  | -    return LCD_BYTESPERPIXEL;
 | 
| 62 |  | -}
 | 
| 63 |  | -
 | 
| 64 |  | -int lcd_get_format()
 | 
| 65 |  | -{
 | 
| 66 |  | -    return LCD_FORMAT;
 | 
| 67 |  | -}
 | 
| 68 |  | -
 | 
| 69 |  | -static void lcd_send_cmd(uint16_t cmd) ICODE_ATTR __attribute__((noinline));
 | 
| 70 |  | -static void lcd_send_cmd(uint16_t cmd)
 | 
| 71 |  | -{
 | 
| 72 |  | -    while (LCDSTATUS & 0x10);
 | 
| 73 |  | -    LCDWCMD = cmd;
 | 
| 74 |  | -}
 | 
| 75 |  | -
 | 
| 76 |  | -static void lcd_send_data(uint16_t data) ICODE_ATTR __attribute__((noinline));
 | 
| 77 |  | -static void lcd_send_data(uint16_t data)
 | 
| 78 |  | -{
 | 
| 79 |  | -    while (LCDSTATUS & 0x10);
 | 
| 80 |  | -    LCDWDATA = data;
 | 
| 81 |  | -}
 | 
| 82 |  | -
 | 
| 83 |  | -static uint32_t lcd_detect() ICODE_ATTR;
 | 
| 84 |  | -static uint32_t lcd_detect()
 | 
| 85 |  | -{
 | 
| 86 |  | -    return (PDAT13 & 1) | (PDAT14 & 2);
 | 
| 87 |  | -}
 | 
| 88 |  | -
 | 
| 89 |  | -bool displaylcd_busy() ICODE_ATTR;
 | 
| 90 |  | -bool displaylcd_busy()
 | 
| 91 |  | -{
 | 
| 92 |  | -    return lcd_dma_busy;
 | 
| 93 |  | -}
 | 
| 94 |  | -
 | 
| 95 |  | -bool displaylcd_safe()
 | 
| 96 |  | -{
 | 
| 97 |  | -    lcd_in_irq = true;
 | 
| 98 |  | -    if (!lcd_dma_busy) return true;
 | 
| 99 |  | -    return !(DMAALLST2 & 0x70000);
 | 
| 100 |  | -}
 | 
| 101 |  | -
 | 
| 102 |  | -void displaylcd_sync() ICODE_ATTR;
 | 
| 103 |  | -void displaylcd_sync()
 | 
| 104 |  | -{
 | 
| 105 |  | -    mutex_lock(&lcd_mutex, TIMEOUT_BLOCK);
 | 
| 106 |  | -    while (displaylcd_busy()) wakeup_wait(&lcd_wakeup, TIMEOUT_BLOCK);
 | 
| 107 |  | -    mutex_unlock(&lcd_mutex);
 | 
| 108 |  | -}
 | 
| 109 |  | -
 | 
| 110 |  | -void displaylcd_setup(unsigned int startx, unsigned int endx,
 | 
| 111 |  | -                      unsigned int starty, unsigned int endy) ICODE_ATTR;
 | 
| 112 |  | -void displaylcd_setup(unsigned int startx, unsigned int endx,
 | 
| 113 |  | -                      unsigned int starty, unsigned int endy)
 | 
| 114 |  | -{
 | 
| 115 |  | -    if (!lcd_in_irq)
 | 
| 116 |  | -    {
 | 
| 117 |  | -        mutex_lock(&lcd_mutex, TIMEOUT_BLOCK);
 | 
| 118 |  | -        displaylcd_sync();
 | 
| 119 |  | -    }
 | 
| 120 |  | -    if (lcd_detect() == 2)
 | 
| 121 |  | -    {
 | 
| 122 |  | -        lcd_send_cmd(0x50);
 | 
| 123 |  | -        lcd_send_data(startx);
 | 
| 124 |  | -        lcd_send_cmd(0x51);
 | 
| 125 |  | -        lcd_send_data(endx);
 | 
| 126 |  | -        lcd_send_cmd(0x52);
 | 
| 127 |  | -        lcd_send_data(starty);
 | 
| 128 |  | -        lcd_send_cmd(0x53);
 | 
| 129 |  | -        lcd_send_data(endy);
 | 
| 130 |  | -        lcd_send_cmd(0x20);
 | 
| 131 |  | -        lcd_send_data(startx);
 | 
| 132 |  | -        lcd_send_cmd(0x21);
 | 
| 133 |  | -        lcd_send_data(starty);
 | 
| 134 |  | -        lcd_send_cmd(0x22);
 | 
| 135 |  | -    }
 | 
| 136 |  | -    else
 | 
| 137 |  | -    {
 | 
| 138 |  | -        lcd_send_cmd(0x2a);
 | 
| 139 |  | -        lcd_send_data(startx);
 | 
| 140 |  | -        lcd_send_data(endx);
 | 
| 141 |  | -        lcd_send_cmd(0x2b);
 | 
| 142 |  | -        lcd_send_data(starty);
 | 
| 143 |  | -        lcd_send_data(endy);
 | 
| 144 |  | -        lcd_send_cmd(0x2c);
 | 
| 145 |  | -    }
 | 
| 146 |  | -}
 | 
| 147 |  | -
 | 
| 148 |  | -static void displaylcd_dma(void* data, int pixels) ICODE_ATTR;
 | 
| 149 |  | -static void displaylcd_dma(void* data, int pixels)
 | 
| 150 |  | -{
 | 
| 151 |  | -    uint16_t* in = (uint16_t*)data;
 | 
| 152 |  | -    while (LCDSTATUS & 8);
 | 
| 153 |  | -    while (pixels & 3)
 | 
| 154 |  | -	{
 | 
| 155 |  | -        LCDWDATA = *in++;
 | 
| 156 |  | -        pixels--;
 | 
| 157 |  | -	}
 | 
| 158 |  | -    lcd_dma_busy = true;
 | 
| 159 |  | -    DMABASE8 = in;
 | 
| 160 |  | -    DMACON8 = 0x20590000;
 | 
| 161 |  | -    DMATCNT8 = pixels / 4;
 | 
| 162 |  | -    clean_dcache();
 | 
| 163 |  | -    DMACOM8 = 4;
 | 
| 164 |  | -}
 | 
| 165 |  | -
 | 
| 166 |  | -static void displaylcd_solid(uint16_t data, int pixels) ICODE_ATTR;
 | 
| 167 |  | -static void displaylcd_solid(uint16_t data, int pixels)
 | 
| 168 |  | -{
 | 
| 169 |  | -    while (pixels >= 4)
 | 
| 170 |  | -    {
 | 
| 171 |  | -        while (LCDSTATUS & 8);
 | 
| 172 |  | -        LCDWDATA = data;
 | 
| 173 |  | -        LCDWDATA = data;
 | 
| 174 |  | -        LCDWDATA = data;
 | 
| 175 |  | -        LCDWDATA = data;
 | 
| 176 |  | -        pixels -= 4;
 | 
| 177 |  | -    }
 | 
| 178 |  | -    while (LCDSTATUS & 8);
 | 
| 179 |  | -    while (pixels & 3)
 | 
| 180 |  | -	{
 | 
| 181 |  | -        LCDWDATA = data;
 | 
| 182 |  | -        pixels--;
 | 
| 183 |  | -	}
 | 
| 184 |  | -}
 | 
| 185 |  | -
 | 
| 186 |  | -void displaylcd_native(unsigned int startx, unsigned int endx,
 | 
| 187 |  | -                       unsigned int starty, unsigned int endy, void* data)
 | 
| 188 |  | -{
 | 
| 189 |  | -    int pixels = (endx - startx + 1) * (endy - starty + 1);
 | 
| 190 |  | -    if (pixels <= 0) return;
 | 
| 191 |  | -    displaylcd_setup(startx, endx, starty, endy);
 | 
| 192 |  | -    displaylcd_dma(data, pixels);
 | 
| 193 |  | -    if (!lcd_in_irq) mutex_unlock(&lcd_mutex);
 | 
| 194 |  | -}
 | 
| 195 |  | -
 | 
| 196 |  | -void filllcd_native(unsigned int startx, unsigned int endx,
 | 
| 197 |  | -                    unsigned int starty, unsigned int endy, int color)
 | 
| 198 |  | -{
 | 
| 199 |  | -    int pixels = (endx - startx + 1) * (endy - starty + 1);
 | 
| 200 |  | -    if (pixels <= 0) return;
 | 
| 201 |  | -    displaylcd_setup(startx, endx, starty, endy);
 | 
| 202 |  | -    displaylcd_solid(color, pixels);
 | 
| 203 |  | -    if (!lcd_in_irq) mutex_unlock(&lcd_mutex);
 | 
| 204 |  | -}
 | 
| 205 |  | -
 | 
| 206 |  | -void displaylcd_dither(unsigned int x, unsigned int y, unsigned int width,
 | 
| 207 |  | -                       unsigned int height, void* data, unsigned int datax,
 | 
| 208 |  | -                       unsigned int datay, unsigned int stride, bool solid)
 | 
| 209 |  | -     ICODE_ATTR __attribute__((naked,noinline));
 | 
| 210 |  | -void displaylcd_dither(unsigned int x, unsigned int y, unsigned int width,
 | 
| 211 |  | -                       unsigned int height, void* data, unsigned int datax,
 | 
| 212 |  | -                       unsigned int datay, unsigned int stride, bool solid)
 | 
| 213 |  | -{
 | 
| 214 |  | -    __asm__ volatile("    muls r12, r2, r3             \n");
 | 
| 215 |  | -    __asm__ volatile("    bxeq lr                      \n");
 | 
| 216 |  | -    __asm__ volatile("    stmfd sp!, {r2-r11,lr}       \n");
 | 
| 217 |  | -    __asm__ volatile("    mov r12, r2                  \n");
 | 
| 218 |  | -    __asm__ volatile("    add r8, r2, r2,lsl#1         \n");
 | 
| 219 |  | -    __asm__ volatile("    add r3, r1, r3               \n");
 | 
| 220 |  | -    __asm__ volatile("    sub r3, r3, #1               \n");
 | 
| 221 |  | -    __asm__ volatile("    mov r2, r1                   \n");
 | 
| 222 |  | -    __asm__ volatile("    add r1, r0, r12              \n");
 | 
| 223 |  | -    __asm__ volatile("    sub r1, r1, #1               \n");
 | 
| 224 |  | -    __asm__ volatile("    bl displaylcd_setup          \n");
 | 
| 225 |  | -    __asm__ volatile("    mov r0, r8                   \n");
 | 
| 226 |  | -    __asm__ volatile("    bl malloc                    \n");
 | 
| 227 |  | -    __asm__ volatile("    cmp r0, #0                   \n");
 | 
| 228 |  | -    __asm__ volatile("    beq displaylcd_dither_unlock \n");
 | 
| 229 |  | -    __asm__ volatile("    mov r2, r8                   \n");
 | 
| 230 |  | -    __asm__ volatile("    mov r1, #0                   \n");
 | 
| 231 |  | -    __asm__ volatile("    mov r8, r0                   \n");
 | 
| 232 |  | -    __asm__ volatile("    bl memset                    \n");
 | 
| 233 |  | -    __asm__ volatile("    ldr r0, [sp,#0x30]           \n");
 | 
| 234 |  | -    __asm__ volatile("    ldr r1, [sp,#0x34]           \n");
 | 
| 235 |  | -    __asm__ volatile("    ldr r11, [sp,#0x38]          \n");
 | 
| 236 |  | -    __asm__ volatile("    ldr r3, [sp,#0x2c]           \n");
 | 
| 237 |  | -    __asm__ volatile("    mla r0, r1, r11, r0          \n");
 | 
| 238 |  | -    __asm__ volatile("    ldr r12, [sp,#0x04]          \n");
 | 
| 239 |  | -    __asm__ volatile("    ldr r2, [sp,#0x3c]           \n");
 | 
| 240 |  | -    __asm__ volatile("    add r3, r3, r0,lsl#1         \n");
 | 
| 241 |  | -    __asm__ volatile("    cmp r2, #0                   \n");
 | 
| 242 |  | -    __asm__ volatile("    ldreq r1, [sp]               \n");
 | 
| 243 |  | -    __asm__ volatile("    add r3, r3, r0               \n");
 | 
| 244 |  | -    __asm__ volatile("    subeq r11, r11, r1           \n");
 | 
| 245 |  | -    __asm__ volatile("    add r11, r11, r11,lsl#1      \n");
 | 
| 246 |  | -    __asm__ volatile("    movne r10, #3                \n");
 | 
| 247 |  | -    __asm__ volatile("    moveq r10, #0                \n");
 | 
| 248 |  | -    __asm__ volatile("    ldr r9, =0x38600040          \n");
 | 
| 249 |  | -    __asm__ volatile("displaylcd_dither_y:             \n");
 | 
| 250 |  | -    __asm__ volatile("    ldr lr, [sp]                 \n");
 | 
| 251 |  | -    __asm__ volatile("    mov r4, #0                   \n");
 | 
| 252 |  | -    __asm__ volatile("    mov r5, #0                   \n");
 | 
| 253 |  | -    __asm__ volatile("    mov r6, #0                   \n");
 | 
| 254 |  | -    __asm__ volatile("    mov r7, r8                   \n");
 | 
| 255 |  | -    __asm__ volatile("displaylcd_dither_x:             \n");
 | 
| 256 |  | -    __asm__ volatile("    mov r2, #0                   \n");
 | 
| 257 |  | -    __asm__ volatile("    ldrb r1, [r3], #1            \n");
 | 
| 258 |  | -    __asm__ volatile("    ldrsb r0, [r7]               \n");
 | 
| 259 |  | -    __asm__ volatile("    add r1, r1, r4               \n");
 | 
| 260 |  | -    __asm__ volatile("    add r1, r1, r0               \n");
 | 
|  | 2 | +// | 
|  | 3 | +// | 
|  | 4 | +//    Copyright 2010 TheSeven | 
|  | 5 | +// | 
|  | 6 | +// | 
|  | 7 | +//    This file is part of emCORE. | 
|  | 8 | +// | 
|  | 9 | +//    emCORE is free software: you can redistribute it and/or | 
|  | 10 | +//    modify it under the terms of the GNU General Public License as | 
|  | 11 | +//    published by the Free Software Foundation, either version 2 of the | 
|  | 12 | +//    License, or (at your option) any later version. | 
|  | 13 | +// | 
|  | 14 | +//    emCORE is distributed in the hope that it will be useful, | 
|  | 15 | +//    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 16 | +//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | 
|  | 17 | +//    See the GNU General Public License for more details. | 
|  | 18 | +// | 
|  | 19 | +//    You should have received a copy of the GNU General Public License along | 
|  | 20 | +//    with emCORE.  If not, see <http://www.gnu.org/licenses/>. | 
|  | 21 | +// | 
|  | 22 | +// | 
|  | 23 | + | 
|  | 24 | + | 
|  | 25 | +#include "global.h" | 
|  | 26 | +#include "thread.h" | 
|  | 27 | +#include "s5l8701.h" | 
|  | 28 | +#include "util.h" | 
|  | 29 | + | 
|  | 30 | + | 
|  | 31 | +static struct mutex lcd_mutex IDATA_ATTR; | 
|  | 32 | +static struct wakeup lcd_wakeup IDATA_ATTR; | 
|  | 33 | + | 
|  | 34 | +static bool lcd_dma_busy IDATA_ATTR; | 
|  | 35 | +static bool lcd_in_irq IDATA_ATTR; | 
|  | 36 | + | 
|  | 37 | + | 
|  | 38 | +void lcd_init() | 
|  | 39 | +{ | 
|  | 40 | +    mutex_init(&lcd_mutex); | 
|  | 41 | +    wakeup_init(&lcd_wakeup); | 
|  | 42 | +    DMACON8 = 0x20590000; | 
|  | 43 | +    LCDCON = 0xd01; | 
|  | 44 | +    LCDPHTIME = 0; | 
|  | 45 | +    lcd_in_irq = false; | 
|  | 46 | +    lcd_dma_busy = false; | 
|  | 47 | +} | 
|  | 48 | + | 
|  | 49 | +int lcd_get_width() | 
|  | 50 | +{ | 
|  | 51 | +    return LCD_WIDTH; | 
|  | 52 | +} | 
|  | 53 | + | 
|  | 54 | +int lcd_get_height() | 
|  | 55 | +{ | 
|  | 56 | +    return LCD_HEIGHT; | 
|  | 57 | +} | 
|  | 58 | + | 
|  | 59 | +int lcd_get_bytes_per_pixel() | 
|  | 60 | +{ | 
|  | 61 | +    return LCD_BYTESPERPIXEL; | 
|  | 62 | +} | 
|  | 63 | + | 
|  | 64 | +int lcd_get_format() | 
|  | 65 | +{ | 
|  | 66 | +    return LCD_FORMAT; | 
|  | 67 | +} | 
|  | 68 | + | 
|  | 69 | +static void lcd_send_cmd(uint16_t cmd) ICODE_ATTR __attribute__((noinline)); | 
|  | 70 | +static void lcd_send_cmd(uint16_t cmd) | 
|  | 71 | +{ | 
|  | 72 | +    while (LCDSTATUS & 0x10); | 
|  | 73 | +    LCDWCMD = cmd; | 
|  | 74 | +} | 
|  | 75 | + | 
|  | 76 | +static void lcd_send_data(uint16_t data) ICODE_ATTR __attribute__((noinline)); | 
|  | 77 | +static void lcd_send_data(uint16_t data) | 
|  | 78 | +{ | 
|  | 79 | +    while (LCDSTATUS & 0x10); | 
|  | 80 | +    LCDWDATA = data; | 
|  | 81 | +} | 
|  | 82 | + | 
|  | 83 | +static uint32_t lcd_detect() ICODE_ATTR; | 
|  | 84 | +static uint32_t lcd_detect() | 
|  | 85 | +{ | 
|  | 86 | +    return (PDAT13 & 1) | (PDAT14 & 2); | 
|  | 87 | +} | 
|  | 88 | + | 
|  | 89 | +bool displaylcd_busy() ICODE_ATTR; | 
|  | 90 | +bool displaylcd_busy() | 
|  | 91 | +{ | 
|  | 92 | +    return lcd_dma_busy; | 
|  | 93 | +} | 
|  | 94 | + | 
|  | 95 | +bool displaylcd_safe() | 
|  | 96 | +{ | 
|  | 97 | +    lcd_in_irq = true; | 
|  | 98 | +    if (!lcd_dma_busy) return true; | 
|  | 99 | +    return !(DMAALLST2 & 0x70000); | 
|  | 100 | +} | 
|  | 101 | + | 
|  | 102 | +void displaylcd_sync() ICODE_ATTR; | 
|  | 103 | +void displaylcd_sync() | 
|  | 104 | +{ | 
|  | 105 | +    mutex_lock(&lcd_mutex, TIMEOUT_BLOCK); | 
|  | 106 | +    while (displaylcd_busy()) wakeup_wait(&lcd_wakeup, TIMEOUT_BLOCK); | 
|  | 107 | +    mutex_unlock(&lcd_mutex); | 
|  | 108 | +} | 
|  | 109 | + | 
|  | 110 | +void displaylcd_setup(unsigned int startx, unsigned int endx, | 
|  | 111 | +                      unsigned int starty, unsigned int endy) ICODE_ATTR; | 
|  | 112 | +void displaylcd_setup(unsigned int startx, unsigned int endx, | 
|  | 113 | +                      unsigned int starty, unsigned int endy) | 
|  | 114 | +{ | 
|  | 115 | +    if (!lcd_in_irq) | 
|  | 116 | +    { | 
|  | 117 | +        mutex_lock(&lcd_mutex, TIMEOUT_BLOCK); | 
|  | 118 | +        displaylcd_sync(); | 
|  | 119 | +    } | 
|  | 120 | +    if (lcd_detect() == 2) | 
|  | 121 | +    { | 
|  | 122 | +        lcd_send_cmd(0x50); | 
|  | 123 | +        lcd_send_data(startx); | 
|  | 124 | +        lcd_send_cmd(0x51); | 
|  | 125 | +        lcd_send_data(endx); | 
|  | 126 | +        lcd_send_cmd(0x52); | 
|  | 127 | +        lcd_send_data(starty); | 
|  | 128 | +        lcd_send_cmd(0x53); | 
|  | 129 | +        lcd_send_data(endy); | 
|  | 130 | +        lcd_send_cmd(0x20); | 
|  | 131 | +        lcd_send_data(startx); | 
|  | 132 | +        lcd_send_cmd(0x21); | 
|  | 133 | +        lcd_send_data(starty); | 
|  | 134 | +        lcd_send_cmd(0x22); | 
|  | 135 | +    } | 
|  | 136 | +    else | 
|  | 137 | +    { | 
|  | 138 | +        lcd_send_cmd(0x2a); | 
|  | 139 | +        lcd_send_data(startx); | 
|  | 140 | +        lcd_send_data(endx); | 
|  | 141 | +        lcd_send_cmd(0x2b); | 
|  | 142 | +        lcd_send_data(starty); | 
|  | 143 | +        lcd_send_data(endy); | 
|  | 144 | +        lcd_send_cmd(0x2c); | 
|  | 145 | +    } | 
|  | 146 | +} | 
|  | 147 | + | 
|  | 148 | +static void displaylcd_dma(void* data, int pixels) ICODE_ATTR; | 
|  | 149 | +static void displaylcd_dma(void* data, int pixels) | 
|  | 150 | +{ | 
|  | 151 | +    uint16_t* in = (uint16_t*)data; | 
|  | 152 | +    while (LCDSTATUS & 8); | 
|  | 153 | +    while (pixels & 3) | 
|  | 154 | +	{ | 
|  | 155 | +        LCDWDATA = *in++; | 
|  | 156 | +        pixels--; | 
|  | 157 | +	} | 
|  | 158 | +    lcd_dma_busy = true; | 
|  | 159 | +    DMABASE8 = in; | 
|  | 160 | +    DMACON8 = 0x20590000; | 
|  | 161 | +    DMATCNT8 = pixels / 4; | 
|  | 162 | +    clean_dcache(); | 
|  | 163 | +    DMACOM8 = 4; | 
|  | 164 | +} | 
|  | 165 | + | 
|  | 166 | +static void displaylcd_solid(uint16_t data, int pixels) ICODE_ATTR; | 
|  | 167 | +static void displaylcd_solid(uint16_t data, int pixels) | 
|  | 168 | +{ | 
|  | 169 | +    while (pixels >= 4) | 
|  | 170 | +    { | 
|  | 171 | +        while (LCDSTATUS & 8); | 
|  | 172 | +        LCDWDATA = data; | 
|  | 173 | +        LCDWDATA = data; | 
|  | 174 | +        LCDWDATA = data; | 
|  | 175 | +        LCDWDATA = data; | 
|  | 176 | +        pixels -= 4; | 
|  | 177 | +    } | 
|  | 178 | +    while (LCDSTATUS & 8); | 
|  | 179 | +    while (pixels & 3) | 
|  | 180 | +	{ | 
|  | 181 | +        LCDWDATA = data; | 
|  | 182 | +        pixels--; | 
|  | 183 | +	} | 
|  | 184 | +} | 
|  | 185 | + | 
|  | 186 | +void displaylcd_native(unsigned int startx, unsigned int endx, | 
|  | 187 | +                       unsigned int starty, unsigned int endy, void* data) | 
|  | 188 | +{ | 
|  | 189 | +    int pixels = (endx - startx + 1) * (endy - starty + 1); | 
|  | 190 | +    if (pixels <= 0) return; | 
|  | 191 | +    displaylcd_setup(startx, endx, starty, endy); | 
|  | 192 | +    displaylcd_dma(data, pixels); | 
|  | 193 | +    if (!lcd_in_irq) mutex_unlock(&lcd_mutex); | 
|  | 194 | +} | 
|  | 195 | + | 
|  | 196 | +void filllcd_native(unsigned int startx, unsigned int endx, | 
|  | 197 | +                    unsigned int starty, unsigned int endy, int color) | 
|  | 198 | +{ | 
|  | 199 | +    int pixels = (endx - startx + 1) * (endy - starty + 1); | 
|  | 200 | +    if (pixels <= 0) return; | 
|  | 201 | +    displaylcd_setup(startx, endx, starty, endy); | 
|  | 202 | +    displaylcd_solid(color, pixels); | 
|  | 203 | +    if (!lcd_in_irq) mutex_unlock(&lcd_mutex); | 
|  | 204 | +} | 
|  | 205 | + | 
|  | 206 | +void displaylcd_dither(unsigned int x, unsigned int y, unsigned int width, | 
|  | 207 | +                       unsigned int height, void* data, unsigned int datax, | 
|  | 208 | +                       unsigned int datay, unsigned int stride, bool solid) | 
|  | 209 | +     ICODE_ATTR __attribute__((naked,noinline)); | 
|  | 210 | +void displaylcd_dither(unsigned int x, unsigned int y, unsigned int width, | 
|  | 211 | +                       unsigned int height, void* data, unsigned int datax, | 
|  | 212 | +                       unsigned int datay, unsigned int stride, bool solid) | 
|  | 213 | +{ | 
|  | 214 | +    __asm__ volatile("    muls r12, r2, r3             \n"); | 
|  | 215 | +    __asm__ volatile("    bxeq lr                      \n"); | 
|  | 216 | +    __asm__ volatile("    stmfd sp!, {r2-r11,lr}       \n"); | 
|  | 217 | +    __asm__ volatile("    mov r12, r2                  \n"); | 
|  | 218 | +    __asm__ volatile("    add r8, r2, r2,lsl#1         \n"); | 
|  | 219 | +    __asm__ volatile("    add r3, r1, r3               \n"); | 
|  | 220 | +    __asm__ volatile("    sub r3, r3, #1               \n"); | 
|  | 221 | +    __asm__ volatile("    mov r2, r1                   \n"); | 
|  | 222 | +    __asm__ volatile("    add r1, r0, r12              \n"); | 
|  | 223 | +    __asm__ volatile("    sub r1, r1, #1               \n"); | 
|  | 224 | +    __asm__ volatile("    bl displaylcd_setup          \n"); | 
|  | 225 | +    __asm__ volatile("    mov r0, r8                   \n"); | 
|  | 226 | +    __asm__ volatile("    bl malloc                    \n"); | 
|  | 227 | +    __asm__ volatile("    cmp r0, #0                   \n"); | 
|  | 228 | +    __asm__ volatile("    beq displaylcd_dither_unlock \n"); | 
|  | 229 | +    __asm__ volatile("    mov r2, r8                   \n"); | 
|  | 230 | +    __asm__ volatile("    mov r1, #0                   \n"); | 
|  | 231 | +    __asm__ volatile("    mov r8, r0                   \n"); | 
|  | 232 | +    __asm__ volatile("    bl memset                    \n"); | 
|  | 233 | +    __asm__ volatile("    ldr r0, [sp,#0x30]           \n"); | 
|  | 234 | +    __asm__ volatile("    ldr r1, [sp,#0x34]           \n"); | 
|  | 235 | +    __asm__ volatile("    ldr r11, [sp,#0x38]          \n"); | 
|  | 236 | +    __asm__ volatile("    ldr r3, [sp,#0x2c]           \n"); | 
|  | 237 | +    __asm__ volatile("    mla r0, r1, r11, r0          \n"); | 
|  | 238 | +    __asm__ volatile("    ldr r12, [sp,#0x04]          \n"); | 
|  | 239 | +    __asm__ volatile("    ldr r2, [sp,#0x3c]           \n"); | 
|  | 240 | +    __asm__ volatile("    add r3, r3, r0,lsl#1         \n"); | 
|  | 241 | +    __asm__ volatile("    cmp r2, #0                   \n"); | 
|  | 242 | +    __asm__ volatile("    ldreq r1, [sp]               \n"); | 
|  | 243 | +    __asm__ volatile("    add r3, r3, r0               \n"); | 
|  | 244 | +    __asm__ volatile("    subeq r11, r11, r1           \n"); | 
|  | 245 | +    __asm__ volatile("    add r11, r11, r11,lsl#1      \n"); | 
|  | 246 | +    __asm__ volatile("    movne r10, #3                \n"); | 
|  | 247 | +    __asm__ volatile("    moveq r10, #0                \n"); | 
|  | 248 | +    __asm__ volatile("    ldr r9, =0x38600040          \n"); | 
|  | 249 | +    __asm__ volatile("displaylcd_dither_y:             \n"); | 
|  | 250 | +    __asm__ volatile("    ldr lr, [sp]                 \n"); | 
|  | 251 | +    __asm__ volatile("    mov r4, #0                   \n"); | 
|  | 252 | +    __asm__ volatile("    mov r5, #0                   \n"); | 
|  | 253 | +    __asm__ volatile("    mov r6, #0                   \n"); | 
|  | 254 | +    __asm__ volatile("    mov r7, r8                   \n"); | 
|  | 255 | +    __asm__ volatile("displaylcd_dither_x:             \n"); | 
|  | 256 | +    __asm__ volatile("    mov r2, #0                   \n"); | 
|  | 257 | +    __asm__ volatile("    ldrb r1, [r3], #1            \n"); | 
|  | 258 | +    __asm__ volatile("    ldrsb r0, [r7]               \n"); | 
|  | 259 | +    __asm__ volatile("    add r1, r1, r4               \n"); | 
|  | 260 | +    __asm__ volatile("    add r1, r1, r0               \n"); | 
| 261 | 261 | __asm__ volatile("    cmp r1, #0xff                \n"); | 
| 262 | 262 | __asm__ volatile("    mvnhi r1, r1,asr#31          \n"); | 
| 263 | 263 | __asm__ volatile("    andhi r1, r1, #0xff          \n"); | 
| 264 |  | -    __asm__ volatile("    mov r0, r1,lsr#3             \n");
 | 
| 265 |  | -    __asm__ volatile("    orr r2, r0,lsl#11            \n");
 | 
| 266 |  | -    __asm__ volatile("    sub r1, r1, r0,lsl#3         \n");
 | 
| 267 |  | -    __asm__ volatile("    sub r1, r1, r0,lsr#2         \n");
 | 
| 268 |  | -    __asm__ volatile("    mov r4, r4,lsr#1             \n");
 | 
| 269 |  | -    __asm__ volatile("    add r4, r4, r1,lsr#2         \n");
 | 
| 270 |  | -    __asm__ volatile("    strb r4, [r7], #1            \n");
 | 
| 271 |  | -    __asm__ volatile("    mov r4, r1,asr#1             \n");
 | 
| 272 |  | -    __asm__ volatile("    ldrb r1, [r3], #1            \n");
 | 
| 273 |  | -    __asm__ volatile("    ldrsb r0, [r7]               \n");
 | 
| 274 |  | -    __asm__ volatile("    add r1, r1, r5               \n");
 | 
| 275 |  | -    __asm__ volatile("    add r1, r1, r0               \n");
 | 
|  | 264 | +    __asm__ volatile("    mov r0, r1,lsr#3             \n"); | 
|  | 265 | +    __asm__ volatile("    orr r2, r0,lsl#11            \n"); | 
|  | 266 | +    __asm__ volatile("    sub r1, r1, r0,lsl#3         \n"); | 
|  | 267 | +    __asm__ volatile("    sub r1, r1, r0,lsr#2         \n"); | 
|  | 268 | +    __asm__ volatile("    mov r4, r4,lsr#1             \n"); | 
|  | 269 | +    __asm__ volatile("    add r4, r4, r1,lsr#2         \n"); | 
|  | 270 | +    __asm__ volatile("    strb r4, [r7], #1            \n"); | 
|  | 271 | +    __asm__ volatile("    mov r4, r1,asr#1             \n"); | 
|  | 272 | +    __asm__ volatile("    ldrb r1, [r3], #1            \n"); | 
|  | 273 | +    __asm__ volatile("    ldrsb r0, [r7]               \n"); | 
|  | 274 | +    __asm__ volatile("    add r1, r1, r5               \n"); | 
|  | 275 | +    __asm__ volatile("    add r1, r1, r0               \n"); | 
| 276 | 276 | __asm__ volatile("    cmp r1, #0xff                \n"); | 
| 277 | 277 | __asm__ volatile("    mvnhi r1, r1,asr#31          \n"); | 
| 278 | 278 | __asm__ volatile("    andhi r1, r1, #0xff          \n"); | 
| 279 |  | -    __asm__ volatile("    mov r0, r1,lsr#2             \n");
 | 
| 280 |  | -    __asm__ volatile("    orr r2, r0,lsl#5             \n");
 | 
| 281 |  | -    __asm__ volatile("    sub r1, r1, r0,lsl#2         \n");
 | 
| 282 |  | -    __asm__ volatile("    sub r1, r1, r0,lsr#4         \n");
 | 
| 283 |  | -    __asm__ volatile("    mov r5, r5,lsr#1             \n");
 | 
| 284 |  | -    __asm__ volatile("    add r5, r5, r1,lsr#2         \n");
 | 
| 285 |  | -    __asm__ volatile("    strb r5, [r7], #1            \n");
 | 
| 286 |  | -    __asm__ volatile("    mov r5, r1,asr#1             \n");
 | 
| 287 |  | -    __asm__ volatile("    ldrb r1, [r3], #1            \n");
 | 
| 288 |  | -    __asm__ volatile("    ldrsb r0, [r7]               \n");
 | 
| 289 |  | -    __asm__ volatile("    add r1, r1, r6               \n");
 | 
| 290 |  | -    __asm__ volatile("    add r1, r1, r0               \n");
 | 
|  | 279 | +    __asm__ volatile("    mov r0, r1,lsr#2             \n"); | 
|  | 280 | +    __asm__ volatile("    orr r2, r0,lsl#5             \n"); | 
|  | 281 | +    __asm__ volatile("    sub r1, r1, r0,lsl#2         \n"); | 
|  | 282 | +    __asm__ volatile("    sub r1, r1, r0,lsr#4         \n"); | 
|  | 283 | +    __asm__ volatile("    mov r5, r5,lsr#1             \n"); | 
|  | 284 | +    __asm__ volatile("    add r5, r5, r1,lsr#2         \n"); | 
|  | 285 | +    __asm__ volatile("    strb r5, [r7], #1            \n"); | 
|  | 286 | +    __asm__ volatile("    mov r5, r1,asr#1             \n"); | 
|  | 287 | +    __asm__ volatile("    ldrb r1, [r3], #1            \n"); | 
|  | 288 | +    __asm__ volatile("    ldrsb r0, [r7]               \n"); | 
|  | 289 | +    __asm__ volatile("    add r1, r1, r6               \n"); | 
|  | 290 | +    __asm__ volatile("    add r1, r1, r0               \n"); | 
| 291 | 291 | __asm__ volatile("    cmp r1, #0xff                \n"); | 
| 292 | 292 | __asm__ volatile("    mvnhi r1, r1,asr#31          \n"); | 
| 293 | 293 | __asm__ volatile("    andhi r1, r1, #0xff          \n"); | 
| 294 |  | -    __asm__ volatile("    mov r0, r1,lsr#3             \n");
 | 
| 295 |  | -    __asm__ volatile("    orr r2, r0                   \n");
 | 
| 296 |  | -    __asm__ volatile("    sub r1, r1, r0,lsl#3         \n");
 | 
| 297 |  | -    __asm__ volatile("    sub r1, r1, r0,lsr#2         \n");
 | 
| 298 |  | -    __asm__ volatile("    mov r6, r6,lsr#1             \n");
 | 
| 299 |  | -    __asm__ volatile("    add r6, r6, r1,lsr#2         \n");
 | 
| 300 |  | -    __asm__ volatile("    strb r6, [r7], #1            \n");
 | 
| 301 |  | -    __asm__ volatile("displaylcd_dither_waitlcd:       \n");
 | 
| 302 |  | -    __asm__ volatile("    ldr r0, [r9,#-0x24]          \n");
 | 
| 303 |  | -    __asm__ volatile("    mov r6, r1,asr#1             \n");
 | 
| 304 |  | -    __asm__ volatile("    tst r0, #0x10                \n");
 | 
| 305 |  | -    __asm__ volatile("    bne displaylcd_dither_waitlcd\n");
 | 
| 306 |  | -    __asm__ volatile("    str r2, [r9]                 \n");
 | 
| 307 |  | -    __asm__ volatile("    sub r3, r3, r10              \n");
 | 
| 308 |  | -    __asm__ volatile("    subs lr, lr, #1              \n");
 | 
| 309 |  | -    __asm__ volatile("    bne displaylcd_dither_x      \n");
 | 
| 310 |  | -    __asm__ volatile("    add r3, r3, r11              \n");
 | 
| 311 |  | -    __asm__ volatile("    subs r12, r12, #1            \n");
 | 
| 312 |  | -    __asm__ volatile("    bne displaylcd_dither_y      \n");
 | 
| 313 |  | -    __asm__ volatile("displaylcd_dither_free:          \n");
 | 
| 314 |  | -    __asm__ volatile("    mov r0, r8                   \n");
 | 
| 315 |  | -    __asm__ volatile("    bl free                      \n");
 | 
| 316 |  | -    __asm__ volatile("displaylcd_dither_unlock:        \n");
 | 
| 317 |  | -    __asm__ volatile("    ldr r0, =lcd_mutex           \n");
 | 
| 318 |  | -    __asm__ volatile("    bl mutex_unlock              \n");
 | 
| 319 |  | -    __asm__ volatile("    ldmfd sp!, {r2-r11,pc}       \n");
 | 
| 320 |  | -}
 | 
| 321 |  | -
 | 
| 322 |  | -void displaylcd(unsigned int x, unsigned int y, unsigned int width, unsigned int height,
 | 
| 323 |  | -                void* data, unsigned int datax, unsigned int datay, unsigned int stride)
 | 
| 324 |  | -{
 | 
| 325 |  | -    displaylcd_dither(x, y, width, height, data, datax, datay, stride, false);
 | 
| 326 |  | -}
 | 
| 327 |  | -
 | 
| 328 |  | -void filllcd(unsigned int x, unsigned int y, unsigned int width, unsigned int height, int color)
 | 
| 329 |  | -{
 | 
| 330 |  | -    if (width * height <= 0) return;
 | 
| 331 |  | -    mutex_lock(&lcd_mutex, TIMEOUT_BLOCK);
 | 
| 332 |  | -    displaylcd_sync();
 | 
| 333 |  | -    displaylcd_dither(x, y, width, height, &color, 0, 0, 0, true);
 | 
| 334 |  | -    mutex_unlock(&lcd_mutex);
 | 
| 335 |  | -}
 | 
| 336 |  | -
 | 
| 337 |  | -void lcd_shutdown()
 | 
| 338 |  | -{
 | 
| 339 |  | -    displaylcd_sync();
 | 
| 340 |  | -    uint32_t type = lcd_detect();
 | 
| 341 |  | -    if (type == 2)
 | 
| 342 |  | -    {
 | 
| 343 |  | -        lcd_send_cmd(0x7);
 | 
| 344 |  | -        lcd_send_data(0x232);
 | 
| 345 |  | -        lcd_send_cmd(0x13);
 | 
| 346 |  | -        lcd_send_data(0x1137);
 | 
| 347 |  | -        lcd_send_cmd(0x7);
 | 
| 348 |  | -        lcd_send_data(0x201);
 | 
| 349 |  | -        lcd_send_cmd(0x13);
 | 
| 350 |  | -        lcd_send_data(0x137);
 | 
| 351 |  | -        lcd_send_cmd(0x7);
 | 
| 352 |  | -        lcd_send_data(0x200);
 | 
| 353 |  | -        lcd_send_cmd(0x10);
 | 
| 354 |  | -        lcd_send_data(0x680);
 | 
| 355 |  | -        lcd_send_cmd(0x12);
 | 
| 356 |  | -        lcd_send_data(0x160);
 | 
| 357 |  | -        lcd_send_cmd(0x13);
 | 
| 358 |  | -        lcd_send_data(0x127);
 | 
| 359 |  | -        lcd_send_cmd(0x10);
 | 
| 360 |  | -        lcd_send_data(0x600);
 | 
| 361 |  | -    }
 | 
| 362 |  | -    else
 | 
| 363 |  | -    {
 | 
| 364 |  | -        lcd_send_cmd(0x28);
 | 
| 365 |  | -        lcd_send_cmd(0x10);
 | 
| 366 |  | -    }
 | 
| 367 |  | -    sleep(5000);
 | 
| 368 |  | -}
 | 
| 369 |  | -
 | 
| 370 |  | -void INT_DMA8()
 | 
| 371 |  | -{
 | 
| 372 |  | -    DMACOM8 = 7;
 | 
| 373 |  | -    lcd_in_irq = true;
 | 
| 374 |  | -    lcd_dma_busy = false;
 | 
| 375 |  | -    lcdconsole_callback();
 | 
| 376 |  | -    wakeup_signal(&lcd_wakeup);
 | 
| 377 |  | -    lcd_in_irq = false;
 | 
| 378 |  | -}
 | 
| 379 |  | -
 | 
| 380 |  | -int lcd_translate_color(uint8_t alpha, uint8_t red, uint8_t green, uint8_t blue)
 | 
| 381 |  | -    ICODE_ATTR __attribute__((naked, noinline));
 | 
| 382 |  | -int lcd_translate_color(uint8_t alpha, uint8_t red, uint8_t green, uint8_t blue)
 | 
| 383 |  | -{
 | 
| 384 |  | -    asm volatile(
 | 
| 385 |  | -        "cmp r0, #0xff             \n\t"
 | 
| 386 |  | -        "moveq r0, #-1             \n\t"
 | 
| 387 |  | -        "moveq pc, lr              \n\t"
 | 
| 388 |  | -        "cmp r0, #0                \n\t"
 | 
| 389 |  | -        "movne r0, #0xff000000     \n\t"
 | 
| 390 |  | -        "orrne r0, r0, #0xff0000   \n\t"
 | 
| 391 |  | -        "mov r2, r2,lsr#2          \n\t"
 | 
| 392 |  | -        "orr r0, r0, r3,lsr#3      \n\t"
 | 
| 393 |  | -        "mov r1, r1,lsr#3          \n\t"
 | 
| 394 |  | -        "orr r0, r0, r2,lsl#5      \n\t"
 | 
| 395 |  | -        "orr r0, r0, r1,lsl#11     \n\t"
 | 
| 396 |  | -        "mov pc, lr                \n\t"
 | 
| 397 |  | -    );
 | 
| 398 |  | -}
 | 
|  | 294 | +    __asm__ volatile("    mov r0, r1,lsr#3             \n"); | 
|  | 295 | +    __asm__ volatile("    orr r2, r0                   \n"); | 
|  | 296 | +    __asm__ volatile("    sub r1, r1, r0,lsl#3         \n"); | 
|  | 297 | +    __asm__ volatile("    sub r1, r1, r0,lsr#2         \n"); | 
|  | 298 | +    __asm__ volatile("    mov r6, r6,lsr#1             \n"); | 
|  | 299 | +    __asm__ volatile("    add r6, r6, r1,lsr#2         \n"); | 
|  | 300 | +    __asm__ volatile("    strb r6, [r7], #1            \n"); | 
|  | 301 | +    __asm__ volatile("displaylcd_dither_waitlcd:       \n"); | 
|  | 302 | +    __asm__ volatile("    ldr r0, [r9,#-0x24]          \n"); | 
|  | 303 | +    __asm__ volatile("    mov r6, r1,asr#1             \n"); | 
|  | 304 | +    __asm__ volatile("    tst r0, #0x10                \n"); | 
|  | 305 | +    __asm__ volatile("    bne displaylcd_dither_waitlcd\n"); | 
|  | 306 | +    __asm__ volatile("    str r2, [r9]                 \n"); | 
|  | 307 | +    __asm__ volatile("    sub r3, r3, r10              \n"); | 
|  | 308 | +    __asm__ volatile("    subs lr, lr, #1              \n"); | 
|  | 309 | +    __asm__ volatile("    bne displaylcd_dither_x      \n"); | 
|  | 310 | +    __asm__ volatile("    add r3, r3, r11              \n"); | 
|  | 311 | +    __asm__ volatile("    subs r12, r12, #1            \n"); | 
|  | 312 | +    __asm__ volatile("    bne displaylcd_dither_y      \n"); | 
|  | 313 | +    __asm__ volatile("displaylcd_dither_free:          \n"); | 
|  | 314 | +    __asm__ volatile("    mov r0, r8                   \n"); | 
|  | 315 | +    __asm__ volatile("    bl free                      \n"); | 
|  | 316 | +    __asm__ volatile("displaylcd_dither_unlock:        \n"); | 
|  | 317 | +    __asm__ volatile("    ldr r0, =lcd_mutex           \n"); | 
|  | 318 | +    __asm__ volatile("    bl mutex_unlock              \n"); | 
|  | 319 | +    __asm__ volatile("    ldmfd sp!, {r2-r11,pc}       \n"); | 
|  | 320 | +} | 
|  | 321 | + | 
|  | 322 | +void displaylcd(unsigned int x, unsigned int y, unsigned int width, unsigned int height, | 
|  | 323 | +                void* data, unsigned int datax, unsigned int datay, unsigned int stride) | 
|  | 324 | +{ | 
|  | 325 | +    displaylcd_dither(x, y, width, height, data, datax, datay, stride, false); | 
|  | 326 | +} | 
|  | 327 | + | 
|  | 328 | +void filllcd(unsigned int x, unsigned int y, unsigned int width, unsigned int height, int color) | 
|  | 329 | +{ | 
|  | 330 | +    if (width * height <= 0) return; | 
|  | 331 | +    mutex_lock(&lcd_mutex, TIMEOUT_BLOCK); | 
|  | 332 | +    displaylcd_sync(); | 
|  | 333 | +    displaylcd_dither(x, y, width, height, &color, 0, 0, 0, true); | 
|  | 334 | +    mutex_unlock(&lcd_mutex); | 
|  | 335 | +} | 
|  | 336 | + | 
|  | 337 | +void lcd_shutdown() | 
|  | 338 | +{ | 
|  | 339 | +    displaylcd_sync(); | 
|  | 340 | +    uint32_t type = lcd_detect(); | 
|  | 341 | +    if (type == 2) | 
|  | 342 | +    { | 
|  | 343 | +        lcd_send_cmd(0x7); | 
|  | 344 | +        lcd_send_data(0x232); | 
|  | 345 | +        lcd_send_cmd(0x13); | 
|  | 346 | +        lcd_send_data(0x1137); | 
|  | 347 | +        lcd_send_cmd(0x7); | 
|  | 348 | +        lcd_send_data(0x201); | 
|  | 349 | +        lcd_send_cmd(0x13); | 
|  | 350 | +        lcd_send_data(0x137); | 
|  | 351 | +        lcd_send_cmd(0x7); | 
|  | 352 | +        lcd_send_data(0x200); | 
|  | 353 | +        lcd_send_cmd(0x10); | 
|  | 354 | +        lcd_send_data(0x680); | 
|  | 355 | +        lcd_send_cmd(0x12); | 
|  | 356 | +        lcd_send_data(0x160); | 
|  | 357 | +        lcd_send_cmd(0x13); | 
|  | 358 | +        lcd_send_data(0x127); | 
|  | 359 | +        lcd_send_cmd(0x10); | 
|  | 360 | +        lcd_send_data(0x600); | 
|  | 361 | +    } | 
|  | 362 | +    else | 
|  | 363 | +    { | 
|  | 364 | +        lcd_send_cmd(0x28); | 
|  | 365 | +        lcd_send_cmd(0x10); | 
|  | 366 | +    } | 
|  | 367 | +    sleep(10000); | 
|  | 368 | +} | 
|  | 369 | + | 
|  | 370 | +void INT_DMA8() | 
|  | 371 | +{ | 
|  | 372 | +    DMACOM8 = 7; | 
|  | 373 | +    lcd_in_irq = true; | 
|  | 374 | +    lcd_dma_busy = false; | 
|  | 375 | +    lcdconsole_callback(); | 
|  | 376 | +    wakeup_signal(&lcd_wakeup); | 
|  | 377 | +    lcd_in_irq = false; | 
|  | 378 | +} | 
|  | 379 | + | 
|  | 380 | +int lcd_translate_color(uint8_t alpha, uint8_t red, uint8_t green, uint8_t blue) | 
|  | 381 | +    ICODE_ATTR __attribute__((naked, noinline)); | 
|  | 382 | +int lcd_translate_color(uint8_t alpha, uint8_t red, uint8_t green, uint8_t blue) | 
|  | 383 | +{ | 
|  | 384 | +    asm volatile( | 
|  | 385 | +        "cmp r0, #0xff             \n\t" | 
|  | 386 | +        "moveq r0, #-1             \n\t" | 
|  | 387 | +        "moveq pc, lr              \n\t" | 
|  | 388 | +        "cmp r0, #0                \n\t" | 
|  | 389 | +        "movne r0, #0xff000000     \n\t" | 
|  | 390 | +        "orrne r0, r0, #0xff0000   \n\t" | 
|  | 391 | +        "mov r2, r2,lsr#2          \n\t" | 
|  | 392 | +        "orr r0, r0, r3,lsr#3      \n\t" | 
|  | 393 | +        "mov r1, r1,lsr#3          \n\t" | 
|  | 394 | +        "orr r0, r0, r2,lsl#5      \n\t" | 
|  | 395 | +        "orr r0, r0, r1,lsl#11     \n\t" | 
|  | 396 | +        "mov pc, lr                \n\t" | 
|  | 397 | +    ); | 
|  | 398 | +} |