A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 964 lines 41 kB view raw
1/*************************************************************************** 2* __________ __ ___. 3* Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7* \/ \/ \/ \/ \/ 8* $Id$ 9* 10* New greyscale framework 11* Core & miscellaneous functions 12* 13* This is a generic framework to display 129 shades of grey on low-depth 14* bitmap LCDs (Archos b&w, Iriver & Ipod 4-grey) within plugins. 15* 16* Copyright (C) 2008 Jens Arnold 17* 18* This program is free software; you can redistribute it and/or 19* modify it under the terms of the GNU General Public License 20* as published by the Free Software Foundation; either version 2 21* of the License, or (at your option) any later version. 22* 23* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 24* KIND, either express or implied. 25* 26****************************************************************************/ 27 28#include "plugin.h" 29#include "grey.h" 30#include "fixedpoint.h" 31 32#if defined(HAVE_ADJUSTABLE_CPU_FREQ) && \ 33 (defined(CPU_PP) || (CONFIG_LCD == LCD_TL0350A)) 34#define NEED_BOOST 35#endif 36 37#ifndef SIMULATOR 38 39#if defined IAUDIO_M3 /* verified */ 40/* Average measurements of 2 iAudio remotes connected to an M3. */ 41static const unsigned char lcdlinear[256] = { 42 5, 9, 13, 17, 21, 26, 30, 34, 38, 42, 46, 50, 54, 58, 62, 66, 43 70, 73, 76, 78, 80, 82, 84, 86, 88, 90, 91, 92, 94, 95, 96, 97, 44 98, 99, 99, 100, 101, 102, 102, 103, 104, 104, 105, 105, 106, 107, 107, 108, 45109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 46117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 121, 122, 122, 123, 123, 123, 47124, 124, 124, 125, 125, 126, 126, 126, 127, 127, 127, 128, 128, 129, 129, 129, 48130, 130, 131, 131, 132, 132, 133, 133, 134, 134, 134, 135, 135, 136, 136, 136, 49137, 137, 137, 138, 138, 139, 139, 139, 140, 140, 141, 141, 142, 142, 143, 143, 50144, 144, 145, 145, 146, 147, 147, 148, 149, 149, 150, 150, 151, 151, 152, 152, 51153, 153, 154, 154, 155, 155, 156, 156, 157, 157, 158, 158, 159, 160, 160, 161, 52162, 162, 163, 164, 164, 165, 166, 167, 168, 168, 169, 169, 170, 171, 171, 172, 53173, 173, 174, 175, 176, 176, 177, 178, 179, 179, 180, 181, 182, 182, 183, 184, 54185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 198, 199, 200, 201, 55202, 203, 204, 205, 207, 208, 209, 210, 211, 212, 213, 214, 216, 217, 218, 219, 56220, 221, 222, 223, 225, 226, 227, 228, 229, 230, 231, 232, 234, 235, 236, 237, 57238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 249, 250, 251, 252 58}; 59/* The actual LCD scanrate is 3x as high, but 150 Hz or 75 Hz cause a too high 60 * CPU load (> 50 %). Even at 50Hz, greyscale display is rather smooth. Average 61 * from 2 iAudio remotes. */ 62#define LCD_SCANRATE 50 /* Hz */ 63 64#elif defined IAUDIO_M5 /* verified */ 65/* Measurement of one iAudio M5L */ 66static const unsigned char lcdlinear[256] = { 67 4, 6, 8, 10, 11, 13, 15, 17, 19, 21, 22, 24, 25, 27, 28, 30, 68 32, 33, 35, 36, 37, 39, 40, 42, 43, 44, 45, 46, 48, 49, 50, 51, 69 52, 52, 53, 54, 55, 55, 56, 57, 58, 58, 59, 60, 61, 61, 62, 63, 70 64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 70, 70, 71, 72, 72, 71 73, 73, 74, 75, 75, 76, 77, 77, 78, 78, 79, 79, 80, 80, 81, 81, 72 82, 82, 83, 84, 84, 85, 86, 86, 87, 87, 88, 89, 89, 90, 91, 91, 73 92, 92, 93, 93, 94, 94, 95, 95, 96, 96, 97, 98, 98, 99, 100, 100, 74101, 101, 102, 102, 103, 103, 104, 104, 105, 105, 106, 106, 107, 107, 108, 108, 75109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 76117, 117, 118, 119, 119, 120, 121, 121, 122, 122, 123, 124, 124, 125, 126, 126, 77127, 127, 128, 129, 130, 130, 131, 132, 133, 133, 134, 135, 135, 136, 137, 137, 78138, 139, 140, 141, 142, 142, 143, 144, 145, 146, 147, 148, 149, 149, 150, 151, 79152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 163, 164, 165, 167, 168, 169, 80170, 172, 173, 175, 177, 179, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 81200, 202, 204, 205, 207, 209, 210, 212, 214, 216, 218, 219, 221, 223, 224, 226, 82228, 230, 231, 233, 235, 236, 237, 239, 241, 243, 244, 246, 248, 249, 250, 252 83}; 84#define LCD_SCANRATE 73 /* Hz */ 85 86#elif defined IPOD_1G2G /* verified */ 87/* Average measurements of an iPod 1st Gen (0x00010001) and an iPod 2nd Gen 88 * (0x00020000), measured with both backlight off & backlight on (flipped 89 * curves) and medium load (white background when measuring with backlight on), 90 * as the curve is load dependent (the controller's step-up converter doesn't 91 * provide enough juice). Table is for backlight_off state. */ 92static const unsigned char lcdlinear[256] = { 93 4, 6, 8, 9, 11, 13, 14, 16, 17, 18, 20, 21, 23, 24, 26, 27, 94 29, 30, 31, 32, 34, 35, 36, 37, 38, 39, 40, 41, 41, 42, 43, 44, 95 45, 45, 46, 47, 47, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 96 54, 54, 54, 55, 55, 56, 56, 56, 57, 57, 57, 58, 58, 59, 59, 59, 97 60, 60, 60, 61, 61, 62, 62, 62, 63, 63, 63, 64, 64, 65, 65, 65, 98 66, 66, 67, 67, 68, 68, 69, 69, 70, 70, 71, 71, 72, 72, 73, 73, 99 74, 74, 74, 75, 75, 76, 76, 76, 77, 77, 78, 78, 79, 79, 80, 80, 100 81, 81, 82, 82, 83, 83, 84, 84, 85, 85, 86, 86, 87, 87, 88, 88, 101 89, 89, 90, 91, 92, 92, 93, 94, 95, 95, 96, 97, 97, 98, 99, 99, 102100, 100, 101, 102, 102, 103, 104, 104, 105, 105, 106, 107, 107, 108, 109, 109, 103110, 110, 111, 112, 113, 113, 114, 115, 116, 116, 117, 118, 119, 119, 120, 121, 104122, 122, 123, 124, 125, 125, 126, 127, 128, 129, 130, 131, 131, 132, 133, 134, 105135, 137, 138, 139, 141, 142, 144, 145, 146, 147, 149, 150, 151, 152, 154, 155, 106156, 158, 159, 161, 162, 164, 165, 167, 169, 171, 172, 174, 175, 177, 178, 180, 107182, 184, 186, 188, 189, 191, 193, 195, 197, 199, 201, 203, 206, 208, 210, 212, 108214, 217, 219, 221, 224, 226, 229, 231, 233, 236, 238, 240, 243, 245, 247, 250 109}; 110/* Average from an iPod 1st Gen and an iPod 2nd Gen */ 111#define LCD_SCANRATE 96 /* Hz */ 112 113#elif defined IPOD_MINI2G /* verified */ \ 114 || defined IPOD_MINI /* should be identical */ \ 115 || defined IPOD_3G /* TODO: verify */ \ 116 || defined IPOD_4G /* TODO: verify */ 117/* Measurement of one iPod Mini G2 */ 118static const unsigned char lcdlinear[256] = { 119 2, 5, 7, 10, 12, 15, 17, 20, 22, 24, 26, 28, 30, 32, 34, 36, 120 38, 40, 41, 42, 44, 45, 46, 47, 48, 49, 50, 50, 51, 52, 52, 53, 121 54, 54, 55, 55, 56, 56, 57, 57, 58, 58, 58, 59, 59, 60, 60, 60, 122 61, 61, 61, 62, 62, 63, 63, 63, 64, 64, 64, 64, 65, 65, 65, 65, 123 66, 66, 66, 66, 67, 67, 67, 67, 68, 68, 68, 68, 69, 69, 69, 69, 124 70, 70, 70, 70, 71, 71, 71, 71, 72, 72, 72, 73, 73, 74, 74, 74, 125 75, 75, 75, 75, 76, 76, 76, 76, 77, 77, 77, 78, 78, 79, 79, 79, 126 80, 80, 80, 81, 81, 82, 82, 82, 83, 83, 83, 84, 84, 85, 85, 85, 127 86, 86, 86, 87, 87, 88, 88, 88, 89, 89, 90, 90, 91, 91, 92, 92, 128 93, 93, 94, 94, 95, 95, 96, 96, 97, 97, 98, 99, 99, 100, 101, 101, 129102, 102, 103, 104, 104, 105, 106, 106, 107, 108, 109, 110, 110, 111, 112, 113, 130114, 115, 115, 116, 117, 118, 118, 119, 120, 121, 121, 122, 123, 124, 124, 125, 131126, 127, 128, 129, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 132141, 142, 143, 144, 146, 147, 148, 149, 150, 151, 153, 154, 155, 156, 158, 159, 133160, 162, 163, 165, 166, 168, 169, 171, 172, 175, 177, 180, 182, 185, 187, 190, 134192, 196, 199, 203, 206, 210, 213, 217, 220, 223, 227, 230, 234, 238, 242, 246 135}; 136/* Average of an iPod Mini G2 and 2 3rd Gen iPods. */ 137#define LCD_SCANRATE 87 /* Hz */ 138 139#elif defined IRIVER_H100_SERIES /* verified */ 140/* Measurement of one Iriver H140 */ 141static const unsigned char lcdlinear[256] = { 142 5, 8, 12, 15, 18, 22, 25, 28, 31, 34, 36, 39, 42, 44, 47, 50, 143 53, 55, 57, 59, 62, 64, 66, 68, 70, 71, 72, 73, 75, 76, 77, 78, 144 79, 80, 80, 81, 82, 83, 83, 84, 85, 85, 86, 86, 87, 87, 88, 88, 145 89, 89, 90, 90, 91, 91, 92, 92, 93, 93, 93, 94, 94, 95, 95, 95, 146 96, 96, 96, 97, 97, 98, 98, 98, 99, 99, 99, 100, 100, 101, 101, 101, 147102, 102, 102, 103, 103, 104, 104, 104, 105, 105, 106, 106, 107, 107, 108, 108, 148109, 109, 109, 110, 110, 111, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 149116, 116, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 150124, 124, 125, 125, 126, 127, 127, 128, 129, 129, 130, 130, 131, 131, 132, 132, 151133, 133, 134, 135, 135, 136, 137, 137, 138, 138, 139, 139, 140, 140, 141, 141, 152142, 142, 143, 143, 144, 145, 145, 146, 147, 147, 148, 148, 149, 150, 150, 151, 153152, 152, 153, 153, 154, 155, 155, 156, 157, 157, 158, 159, 160, 160, 161, 162, 154163, 164, 165, 166, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 155178, 179, 181, 182, 183, 184, 186, 187, 188, 189, 191, 192, 193, 194, 196, 197, 156198, 200, 202, 203, 205, 207, 208, 210, 212, 214, 215, 217, 218, 220, 221, 223, 157224, 226, 228, 229, 231, 233, 235, 236, 238, 240, 241, 242, 244, 245, 246, 248 158}; 159#define LCD_SCANRATE 70 /* Hz */ 160 161#elif defined MROBE_100 /* verified */ 162/* Average measurements of 2 m:robe 100 s */ 163static const unsigned char lcdlinear[256] = { 164 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 49, 53, 56, 60, 63, 67, 165 70, 73, 76, 79, 81, 84, 87, 90, 92, 95, 97, 100, 102, 105, 107, 110, 166112, 114, 116, 118, 119, 121, 123, 125, 126, 128, 130, 131, 133, 135, 136, 138, 167139, 141, 142, 143, 144, 146, 147, 148, 149, 150, 151, 152, 154, 155, 156, 157, 168158, 159, 160, 161, 161, 162, 163, 164, 165, 166, 167, 168, 168, 169, 170, 171, 169172, 172, 173, 173, 174, 174, 175, 175, 176, 176, 177, 178, 178, 179, 180, 180, 170181, 181, 182, 182, 183, 183, 184, 184, 185, 185, 186, 186, 187, 187, 188, 188, 171189, 189, 190, 190, 191, 191, 192, 192, 193, 193, 193, 194, 194, 195, 195, 195, 172196, 196, 197, 197, 198, 198, 199, 199, 200, 200, 200, 201, 201, 202, 202, 202, 173203, 203, 204, 204, 205, 205, 206, 206, 207, 207, 207, 208, 208, 209, 209, 209, 174210, 210, 210, 211, 211, 212, 212, 212, 213, 213, 213, 214, 214, 215, 215, 215, 175216, 216, 216, 217, 217, 218, 218, 218, 219, 219, 219, 220, 220, 221, 221, 221, 176222, 222, 222, 223, 223, 224, 224, 224, 225, 225, 225, 226, 226, 227, 227, 227, 177228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 232, 233, 233, 234, 234, 234, 178235, 235, 235, 236, 236, 237, 237, 237, 238, 238, 238, 239, 239, 240, 240, 240, 179241, 241, 242, 242, 243, 243, 244, 244, 247, 248, 248, 249, 250, 250, 251, 252 180}; 181#define LCD_SCANRATE 51 /* Hz */ 182 183#elif defined SANSA_CLIP /* TODO: calibrate */ 184static const unsigned char lcdlinear[256] = { 185 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 186 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 187 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 188 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 189 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 190 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 191 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 192112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 193128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 194144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 195160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 196176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 197192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 198208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 199224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 200240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 201}; 202#define LCD_SCANRATE 78 /* Hz */ 203 204#elif defined SANSA_CLIPV2 /* TODO: calibrate */ 205static const unsigned char lcdlinear[256] = { 206 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 207 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 208 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 209 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 210 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 211 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 212 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 213112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 214128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 215144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 216160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 217176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 218192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 219208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 220224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 221240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 222}; 223#define LCD_SCANRATE 74 /* Hz */ 224 225#elif defined SANSA_CLIPPLUS /* TODO: calibrate */ 226static const unsigned char lcdlinear[256] = { 227 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 228 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 229 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 230 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 231 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 232 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 233 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 234112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 235128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 236144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 237160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 238176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 239192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 240208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 241224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 242240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 243}; 244#define LCD_SCANRATE 80 /* Hz */ 245 246#elif defined MPIO_HD200 247/* matrix generated in the following way 248 * 1) run 5 times test_grey 249 * 2) average results (joint points) 250 * 3) plot full matrix obtained by natural cubic b-spline interpolation 251 * 4) hand tweak joint points to smooth the curve 252 * 5) repeat steps 3 and 4 until interpolated curve is smooth 253 */ 254static const unsigned char lcdlinear[256] = { 255 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 256 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 257 16, 16, 16, 17, 17, 18, 18, 18, 19, 19, 20, 20, 20, 21, 21, 21, 258 22, 22, 22, 22, 23, 23, 23, 24, 24, 24, 24, 25, 25, 25, 26, 26, 259 27, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, 32, 32, 33, 33, 34, 260 35, 35, 36, 36, 37, 37, 38, 39, 39, 40, 41, 41, 42, 43, 43, 44, 261 45, 45, 46, 46, 47, 48, 49, 49, 50, 51, 51, 52, 53, 53, 54, 55, 262 56, 56, 57, 58, 58, 59, 60, 61, 61, 62, 63, 64, 64, 65, 66, 67, 263 68, 68, 69, 70, 71, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 264 81, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 265 96, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 108, 109, 110, 111, 266113, 114, 115, 117, 118, 120, 121, 123, 125, 126, 128, 130, 131, 133, 135, 137, 267139, 140, 142, 144, 146, 147, 149, 151, 152, 154, 156, 157, 159, 161, 162, 164, 268166, 167, 169, 170, 172, 173, 175, 176, 177, 179, 180, 182, 183, 184, 186, 187, 269189, 190, 191, 193, 194, 195, 197, 198, 199, 201, 202, 203, 205, 206, 207, 208, 270210, 211, 212, 213, 214, 215, 217, 218, 219, 220, 221, 222, 223, 224, 225, 227 271}; 272#define LCD_SCANRATE 153 /* Hz */ 273 274#elif defined MPIO_HD300 /* verified */ 275/* Measurement of one iAudio M5L */ 276static const unsigned char lcdlinear[256] = { 277 4, 6, 8, 10, 11, 13, 15, 17, 19, 21, 22, 24, 25, 27, 28, 30, 278 32, 33, 35, 36, 37, 39, 40, 42, 43, 44, 45, 46, 48, 49, 50, 51, 279 52, 52, 53, 54, 55, 55, 56, 57, 58, 58, 59, 60, 61, 61, 62, 63, 280 64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 70, 70, 71, 72, 72, 281 73, 73, 74, 75, 75, 76, 77, 77, 78, 78, 79, 79, 80, 80, 81, 81, 282 82, 82, 83, 84, 84, 85, 86, 86, 87, 87, 88, 89, 89, 90, 91, 91, 283 92, 92, 93, 93, 94, 94, 95, 95, 96, 96, 97, 98, 98, 99, 100, 100, 284101, 101, 102, 102, 103, 103, 104, 104, 105, 105, 106, 106, 107, 107, 108, 108, 285109, 109, 110, 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 286117, 117, 118, 119, 119, 120, 121, 121, 122, 122, 123, 124, 124, 125, 126, 126, 287127, 127, 128, 129, 130, 130, 131, 132, 133, 133, 134, 135, 135, 136, 137, 137, 288138, 139, 140, 141, 142, 142, 143, 144, 145, 146, 147, 148, 149, 149, 150, 151, 289152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 163, 164, 165, 167, 168, 169, 290170, 172, 173, 175, 177, 179, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 291200, 202, 204, 205, 207, 209, 210, 212, 214, 216, 218, 219, 221, 223, 224, 226, 292228, 230, 231, 233, 235, 236, 237, 239, 241, 243, 244, 246, 248, 249, 250, 252 293}; 294#define LCD_SCANRATE 73 /* Hz */ 295 296#else /* not yet calibrated targets - generic linear mapping */ 297static const unsigned char lcdlinear[256] = { 298 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 299 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 300 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 301 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 302 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 303 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 304 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 305112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 306128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 307144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 308160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 309176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 310192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 311208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 312224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 313240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 314}; 315/* generic default */ 316#define LCD_SCANRATE 70 /* Hz */ 317 318#endif 319#else /* SIMULATOR */ 320/* undo a (generic) PC display gamma of 2.0 to simulate target behaviour */ 321static const unsigned char lcdlinear[256] = { 322 0, 16, 23, 28, 32, 36, 39, 42, 45, 48, 50, 53, 55, 58, 60, 62, 323 64, 66, 68, 70, 71, 73, 75, 77, 78, 80, 81, 83, 84, 86, 87, 89, 324 90, 92, 93, 94, 96, 97, 98, 100, 101, 102, 103, 105, 106, 107, 108, 109, 325111, 112, 113, 114, 115, 116, 117, 118, 119, 121, 122, 123, 124, 125, 126, 127, 326128, 129, 130, 131, 132, 133, 134, 135, 135, 136, 137, 138, 139, 140, 141, 142, 327143, 144, 145, 145, 146, 147, 148, 149, 150, 151, 151, 152, 153, 154, 155, 156, 328156, 157, 158, 159, 160, 160, 161, 162, 163, 164, 164, 165, 166, 167, 167, 168, 329169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176, 177, 178, 179, 179, 180, 330181, 181, 182, 183, 183, 184, 185, 186, 186, 187, 188, 188, 189, 190, 190, 191, 331192, 192, 193, 194, 194, 195, 196, 196, 197, 198, 198, 199, 199, 200, 201, 201, 332202, 203, 203, 204, 204, 205, 206, 206, 207, 208, 208, 209, 209, 210, 211, 211, 333212, 212, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 220, 220, 221, 334221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227, 228, 228, 229, 229, 230, 335230, 231, 231, 232, 233, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, 336239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 247, 337247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253, 253, 254, 254, 255 338}; 339#endif /* SIMULATOR */ 340 341/* Prototypes */ 342static inline void _deferred_update(void) __attribute__ ((always_inline)); 343static void grey_screendump_hook(int fd); 344static void fill_gvalues(void); 345#ifdef SIMULATOR 346static unsigned long _grey_get_pixel(int x, int y); 347#else 348static void _timer_isr(void); 349#endif 350 351 352#if defined(HAVE_BACKLIGHT_INVERSION) && !defined(SIMULATOR) 353static void invert_gvalues(void) 354{ 355 unsigned char *val, *end; 356 unsigned char rev_tab[256]; 357 unsigned i; 358 unsigned last_i = 0; 359 unsigned x = 0; 360 unsigned last_x; 361 362 /* Step 1: Calculate a transposed table for undoing the old mapping */ 363 for (i = 0; i < 256; i++) 364 { 365 last_x = x; 366 x = _grey_info.gvalue[i]; 367 if (x > last_x) 368 { 369 rev_tab[last_x++] = (last_i + i) / 2; 370 while (x > last_x) 371 rev_tab[last_x++] = i; 372 last_i = i; 373 } 374 } 375 rev_tab[last_x++] = (last_i + 255) / 2; 376 while (256 > last_x) 377 rev_tab[last_x++] = 255; 378 379 /* Step 2: Calculate new mapping */ 380 fill_gvalues(); 381 382 /* Step 3: Transpose all pixel values */ 383 val = _grey_info.values; 384 end = val + _GREY_MULUQ(_grey_info.width, _grey_info.height); 385 386 do 387 *val = _grey_info.gvalue[rev_tab[*val]]; 388 while (++val < end); 389} 390#endif 391 392/* Update LCD areas not covered by the greyscale overlay */ 393static inline void _deferred_update(void) 394{ 395 int x1 = MAX(_grey_info.x, 0); 396 int x2 = MIN(_grey_info.x + _grey_info.width, LCD_WIDTH); 397 int y1 = MAX(_grey_info.y, 0); 398 int y2 = MIN(_grey_info.y + _grey_info.height, LCD_HEIGHT); 399 400 if (y1 > 0) /* refresh part above overlay, full width */ 401 rb->lcd_update_rect(0, 0, LCD_WIDTH, y1); 402 403 if (y2 < LCD_HEIGHT) /* refresh part below overlay, full width */ 404 rb->lcd_update_rect(0, y2, LCD_WIDTH, LCD_HEIGHT - y2); 405 406 if (x1 > 0) /* refresh part to the left of overlay */ 407 rb->lcd_update_rect(0, y1, x1, y2 - y1); 408 409 if (x2 < LCD_WIDTH) /* refresh part to the right of overlay */ 410 rb->lcd_update_rect(x2, y1, LCD_WIDTH - x2, y2 - y1); 411} 412 413#ifdef SIMULATOR 414 415/* Callback function for grey_ub_gray_bitmap_part() to read a pixel from the 416 * greybuffer. Note that x and y are in LCD coordinates, not greybuffer 417 * coordinates! */ 418static unsigned long _grey_get_pixel(int x, int y) 419{ 420 long val; 421 int xg = x - _grey_info.x; 422 int yg = y - _grey_info.y; 423#if LCD_PIXELFORMAT == HORIZONTAL_PACKING 424 int idx = _grey_info.width * yg + xg; 425#else /* vertical packing or vertical interleaved */ 426 int idx = _grey_info.width * (yg & ~_GREY_BMASK) 427 + (xg << _GREY_BSHIFT) + (~yg & _GREY_BMASK); 428#endif 429 430 val = _grey_info.values[idx]; 431#ifdef HAVE_LCD_SPLIT 432 val -= val >> 7; 433#endif 434 return val; 435} 436 437#else /* !SIMULATOR */ 438 439/* Timer interrupt handler: display next frame */ 440static void _timer_isr(void) 441{ 442#if defined(HAVE_BACKLIGHT_INVERSION) && !defined(SIMULATOR) 443 unsigned long check = rb->is_backlight_on(true) 444 ? 0 : _GREY_BACKLIGHT_ON; 445 446 if ((_grey_info.flags & (_GREY_BACKLIGHT_ON|GREY_RAWMAPPED)) == check) 447 { 448 _grey_info.flags ^= _GREY_BACKLIGHT_ON; 449 invert_gvalues(); 450 return; /* don't overload this timer slot */ 451 } 452#endif 453#if LCD_PIXELFORMAT == HORIZONTAL_PACKING 454 rb->lcd_blit_grey_phase(_grey_info.values, _grey_info.phases, 455 _grey_info.bx, _grey_info.y, 456 _grey_info.bwidth, _grey_info.height, 457 _grey_info.width); 458#else /* vertical packing or vertical interleaved */ 459 rb->lcd_blit_grey_phase(_grey_info.values, _grey_info.phases, 460 _grey_info.x, _grey_info.by, 461 _grey_info.width, _grey_info.bheight, 462 _grey_info.width); 463#endif 464 465 if (_grey_info.flags & _GREY_DEFERRED_UPDATE) /* lcd_update() requested? */ 466 { 467 _deferred_update(); 468 _grey_info.flags &= ~_GREY_DEFERRED_UPDATE; /* clear request */ 469 } 470} 471 472#endif /* !SIMULATOR */ 473 474static void fill_gvalues(void) 475{ 476 int i; 477 unsigned data; 478 479#if defined(HAVE_BACKLIGHT_INVERSION) && !defined(SIMULATOR) 480 unsigned imask = (_grey_info.flags & _GREY_BACKLIGHT_ON) ? 0xff : 0; 481#else 482 const unsigned imask = 0; 483#endif 484 for (i = 0; i < 256; i++) 485 { 486 data = fp16_exp((_GREY_GAMMA * fp16_log(i * 257 + 1)) >> 8) + 128; 487 data = (data - (data >> 8)) >> 8; /* approx. data /= 257 */ 488 data = ((lcdlinear[data ^ imask] ^ imask) << 7) + 127; 489 _grey_info.gvalue[i] = (data + (data >> 8)) >> 8; 490 /* approx. data / 255 */ 491 } 492} 493 494/* Initialise the framework and prepare the greyscale display buffer 495 496 arguments: 497 gbuf = pointer to the memory area to use (e.g. plugin buffer) 498 gbuf_size = max usable size of the buffer 499 features = flags for requesting features 500 GREY_BUFFERED: use chunky pixel buffering 501 This allows to use all drawing functions, but needs more 502 memory. Unbuffered operation provides only a subset of 503 drawing functions. (only grey_bitmap drawing and scrolling) 504 GREY_RAWMAPPED: no LCD linearisation and gamma correction 505 width = width in pixels (1..LCD_WIDTH) 506 height = height in pixels (1..LCD_HEIGHT) 507 Note that depending on the target LCD, either height or 508 width are rounded up to a multiple of 4 or 8. 509 510 result: 511 true on success, false on failure 512 513 If you need info about the memory taken by the greyscale buffer, supply a 514 long* as the last parameter. This long will then contain the number of bytes 515 used. The total memory needed can be calculated as follows: 516 total_mem = 517 width * height * 2 [grey display data] 518 + buffered ? (width * height) : 0 [chunky buffer] 519 + 0..3 [alignment] 520 521 The function is authentic regarding memory usage on the simulator, even 522 if it doesn't use all of the allocated memory. */ 523bool grey_init(unsigned char *gbuf, long gbuf_size, 524 unsigned features, int width, int height, long *buf_taken) 525{ 526 int bdim, i; 527 long plane_size, buftaken; 528 unsigned data; 529#ifndef SIMULATOR 530 unsigned *dst, *end; 531#endif 532 533 if ((unsigned) width > LCD_WIDTH 534 || (unsigned) height > LCD_HEIGHT) 535 return false; 536 537#if LCD_PIXELFORMAT == HORIZONTAL_PACKING 538 bdim = (width + 7) >> 3; 539 width = bdim << 3; 540#else /* vertical packing or vertical interleaved */ 541#if (LCD_DEPTH == 1) || (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED) 542 bdim = (height + 7) >> 3; 543 height = bdim << 3; 544#elif LCD_DEPTH == 2 545 bdim = (height + 3) >> 2; 546 height = bdim << 2; 547#endif 548#endif 549 550 plane_size = _GREY_MULUQ(width, height); 551#if defined(CPU_COLDFIRE) /* Buffers should be line aligned */ \ 552 || defined(CPU_PP) && (NUM_CORES > 1) /* Buffers must be cache line aligned */ 553 plane_size += (-plane_size) & 0xf; 554 buftaken = (-(long)gbuf) & 0xf; 555#else /* Buffers must be 32 bit aligned. */ 556 buftaken = (-(long)gbuf) & 3; 557#endif 558 gbuf += buftaken; 559 560 if (features & GREY_BUFFERED) /* chunky buffer */ 561 { 562 _grey_info.buffer = gbuf; 563 gbuf += plane_size; 564 buftaken += plane_size; 565 } 566#if NUM_CORES > 1 /* Values and phases must be uncached when running on COP */ 567 if (features & GREY_ON_COP) 568 gbuf = UNCACHED_ADDR(gbuf); 569#endif 570 _grey_info.values = gbuf; 571 gbuf += plane_size; 572 _grey_info.phases = gbuf; 573 buftaken += 2 * plane_size; 574 575 if (buftaken > gbuf_size) 576 return false; 577 578 /* Init to white */ 579 rb->memset(_grey_info.values, 0x80, plane_size); 580 581#ifndef SIMULATOR 582 /* Init phases with random bits */ 583 dst = (unsigned*)(_grey_info.phases); 584 end = (unsigned*)(_grey_info.phases + plane_size); 585 586 do 587 *dst++ = rb->rand(); 588 while (dst < end); 589#endif 590 591 _grey_info.x = 0; 592 _grey_info.y = 0; 593 _grey_info.width = width; 594 _grey_info.height = height; 595#if LCD_PIXELFORMAT == HORIZONTAL_PACKING 596 _grey_info.bx = 0; 597 _grey_info.bwidth = bdim; 598#else /* vertical packing or vertical interleaved */ 599 _grey_info.by = 0; 600 _grey_info.bheight = bdim; 601#endif 602 _grey_info.flags = features & 0xff; 603 604 /* default viewport and settings */ 605 grey_set_viewport(NULL); 606 grey_viewport_set_fullscreen(NULL, SCREEN_MAIN); 607 grey_set_framebuffer(NULL); 608 609 /* precalculate the value -> pattern index conversion table, taking 610 linearisation and gamma correction into account */ 611 if (features & GREY_RAWMAPPED) 612 { 613 for (i = 0; i < 256; i++) 614 { 615 data = i << 7; 616 _grey_info.gvalue[i] = (data + (data >> 8)) >> 8; 617 } 618 } 619 else 620 { 621#if defined(HAVE_BACKLIGHT_INVERSION) && !defined(SIMULATOR) 622 if (rb->is_backlight_on(true)) 623 _grey_info.flags |= _GREY_BACKLIGHT_ON; 624#endif 625 fill_gvalues(); 626 } 627 628 if (buf_taken) /* caller requested info about space taken */ 629 *buf_taken = buftaken; 630 631 return true; 632} 633 634/* Release the greyscale display buffer and the library 635 DO CALL either this function or at least grey_show_display(false) 636 before you exit, otherwise nasty things may happen. */ 637void grey_release(void) 638{ 639 grey_show(false); 640} 641 642/* Switch the greyscale overlay on or off 643 DO NOT call lcd_update() or any other api function that directly accesses 644 the lcd while the greyscale overlay is running! If you need to do 645 lcd_update() to update something outside the greyscale overlay area, use 646 grey_deferred_update() instead. 647 648 Other functions to avoid are: 649 lcd_blit_mono(), lcd_update_rect(), lcd_set_contrast(), 650 lcd_set_invert_display(), lcd_set_flip() */ 651void grey_show(bool enable) 652{ 653 if (enable && !(_grey_info.flags & _GREY_RUNNING)) 654 { 655 _grey_info.flags |= _GREY_RUNNING; 656#ifdef SIMULATOR 657 rb->sim_lcd_ex_init(_grey_get_pixel); 658 rb->sim_lcd_ex_update_rect(_grey_info.x, _grey_info.y, 659 _grey_info.width, _grey_info.height); 660#else /* !SIMULATOR */ 661#ifdef NEED_BOOST 662 rb->cpu_boost(true); 663#endif 664#if NUM_CORES > 1 665 rb->timer_register(1, NULL, TIMER_FREQ / LCD_SCANRATE, 666 _timer_isr, 667 (_grey_info.flags & GREY_ON_COP) ? COP : CPU); 668#else 669 rb->timer_register(1, NULL, TIMER_FREQ / LCD_SCANRATE, _timer_isr); 670#endif 671#endif /* !SIMULATOR */ 672 rb->screen_dump_set_hook(grey_screendump_hook); 673 } 674 else if (!enable && (_grey_info.flags & _GREY_RUNNING)) 675 { 676#ifdef SIMULATOR 677 rb->sim_lcd_ex_init(NULL); 678#else /* !SIMULATOR */ 679 rb->timer_unregister(); 680#if NUM_CORES > 1 /* Make sure the ISR has finished before calling lcd_update() */ 681 rb->sleep(HZ/100); 682#endif 683#ifdef NEED_BOOST 684 rb->cpu_boost(false); 685#endif 686#endif /* !SIMULATOR */ 687 _grey_info.flags &= ~_GREY_RUNNING; 688 rb->screen_dump_set_hook(NULL); 689 rb->lcd_update(); /* restore whatever there was before */ 690 } 691} 692 693void grey_update_rect(int x, int y, int width, int height) 694{ 695 grey_ub_gray_bitmap_part(_grey_info.buffer, x, y, _grey_info.width, 696 x, y, width, height); 697} 698 699/* Update the whole greyscale overlay */ 700void grey_update(void) 701{ 702 grey_ub_gray_bitmap_part(_grey_info.buffer, 0, 0, _grey_info.width, 703 0, 0, _grey_info.width, _grey_info.height); 704} 705 706/* Do an lcd_update() to show changes done by rb->lcd_xxx() functions 707 (in areas of the screen not covered by the greyscale overlay). */ 708void grey_deferred_lcd_update(void) 709{ 710 if (_grey_info.flags & _GREY_RUNNING) 711 { 712#ifdef SIMULATOR 713 _deferred_update(); 714#else 715 _grey_info.flags |= _GREY_DEFERRED_UPDATE; 716#endif 717 } 718 else 719 rb->lcd_update(); 720} 721 722/*** Screenshot ***/ 723 724#ifdef HAVE_LCD_SPLIT 725#define NUM_SHADES 128 726#define BMP_NUMCOLORS 256 727#else 728#define NUM_SHADES 129 729#define BMP_NUMCOLORS 129 730#endif 731 732#define BMP_BPP 8 733#define BMP_LINESIZE ((LCD_WIDTH + 3) & ~3) 734#define BMP_HEADERSIZE (54 + 4 * BMP_NUMCOLORS) 735#define BMP_DATASIZE (BMP_LINESIZE * (LCD_HEIGHT+LCD_SPLIT_LINES)) 736#define BMP_TOTALSIZE (BMP_HEADERSIZE + BMP_DATASIZE) 737 738static const unsigned char bmpheader[] = 739{ 740 0x42, 0x4d, /* 'BM' */ 741 LE32_CONST(BMP_TOTALSIZE), /* Total file size */ 742 0x00, 0x00, 0x00, 0x00, /* Reserved */ 743 LE32_CONST(BMP_HEADERSIZE), /* Offset to start of pixel data */ 744 745 0x28, 0x00, 0x00, 0x00, /* Size of (2nd) header */ 746 LE32_CONST(LCD_WIDTH), /* Width in pixels */ 747 LE32_CONST(LCD_HEIGHT+LCD_SPLIT_LINES), /* Height in pixels */ 748 0x01, 0x00, /* Number of planes (always 1) */ 749 LE16_CONST(BMP_BPP), /* Bits per pixel 1/4/8/16/24 */ 750 0x00, 0x00, 0x00, 0x00, /* Compression mode, 0 = none */ 751 LE32_CONST(BMP_DATASIZE), /* Size of bitmap data */ 752 0xc4, 0x0e, 0x00, 0x00, /* Horizontal resolution (pixels/meter) */ 753 0xc4, 0x0e, 0x00, 0x00, /* Vertical resolution (pixels/meter) */ 754 LE32_CONST(BMP_NUMCOLORS), /* Number of used colours */ 755 LE32_CONST(BMP_NUMCOLORS), /* Number of important colours */ 756}; 757 758#if LCD_DEPTH == 2 759/* Only defined for positive, non-split LCD for now */ 760static const unsigned char colorindex[4] = {128, 85, 43, 0}; 761#endif 762 763/* Hook function for core screen_dump() to save the current display 764 content (b&w and greyscale overlay) to an 8-bit BMP file. */ 765static void grey_screendump_hook(int fd) 766{ 767 fb_data *lcd_fb; 768 struct viewport *vp_main = rb->lcd_set_viewport(NULL); 769 rb->viewport_set_fullscreen(vp_main, SCREEN_MAIN); 770 lcd_fb = vp_main->buffer->fb_ptr; 771 772 int i; 773 int y, gx, gy; 774#if LCD_PIXELFORMAT == VERTICAL_PACKING 775#if LCD_DEPTH == 1 776 unsigned val; 777 unsigned mask; 778#elif LCD_DEPTH == 2 779 int shift; 780#endif 781#elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED 782 unsigned data; 783 int shift; 784#endif /* LCD_PIXELFORMAT */ 785 fb_data *src; 786 unsigned char *gsrc; 787 unsigned char *dst, *dst_end; 788 unsigned char linebuf[MAX(4*NUM_SHADES,BMP_LINESIZE)]; 789 790 rb->write(fd, bmpheader, sizeof(bmpheader)); /* write header */ 791 792 /* build clut */ 793 rb->memset(linebuf, 0, 4*NUM_SHADES); 794 dst = linebuf; 795 796 for (i = 0; i < NUM_SHADES; i++) 797 { 798 *dst++ = (_GREY_MULUQ(BLUE_CMP(LCD_BL_BRIGHTCOLOR) 799 -BLUE_CMP(LCD_BL_DARKCOLOR), i) >> 7) 800 + BLUE_CMP(LCD_BL_DARKCOLOR); 801 *dst++ = (_GREY_MULUQ(GREEN_CMP(LCD_BL_BRIGHTCOLOR) 802 -GREEN_CMP(LCD_BL_DARKCOLOR), i) >> 7) 803 + GREEN_CMP(LCD_BL_DARKCOLOR); 804 *dst++ = (_GREY_MULUQ(RED_CMP(LCD_BL_BRIGHTCOLOR) 805 -RED_CMP(LCD_BL_DARKCOLOR), i) >> 7) 806 + RED_CMP(LCD_BL_DARKCOLOR); 807 dst++; 808 } 809 rb->write(fd, linebuf, 4*NUM_SHADES); 810 811#ifdef HAVE_LCD_SPLIT 812 dst = linebuf; 813 814 for (i = 0; i <= NUM_SHADES; i++) 815 { 816 *dst++ = (_GREY_MULUQ(BLUE_CMP(LCD_BL_BRIGHTCOLOR_2) 817 -BLUE_CMP(LCD_BL_DARKCOLOR_2), i) >> 7) 818 + BLUE_CMP(LCD_BL_DARKCOLOR_2); 819 *dst++ = (_GREY_MULUQ(GREEN_CMP(LCD_BL_BRIGHTCOLOR_2) 820 -GREEN_CMP(LCD_BL_DARKCOLOR_2), i) >> 7) 821 + GREEN_CMP(LCD_BL_DARKCOLOR_2); 822 *dst++ = (_GREY_MULUQ(RED_CMP(LCD_BL_BRIGHTCOLOR_2) 823 -RED_CMP(LCD_BL_DARKCOLOR_2), i) >> 7) 824 + RED_CMP(LCD_BL_DARKCOLOR_2); 825 dst++; 826 } 827 rb->write(fd, linebuf, 4*NUM_SHADES); 828#endif 829 830 /* BMP image goes bottom -> top */ 831 for (y = LCD_HEIGHT - 1; y >= 0; y--) 832 { 833 rb->memset(linebuf, 0, BMP_LINESIZE); 834 835#if defined(HAVE_LCD_SPLIT) && (LCD_SPLIT_LINES == 2) 836 if (y == LCD_SPLIT_POS - 1) 837 { 838 rb->write(fd, linebuf, BMP_LINESIZE); 839 rb->write(fd, linebuf, BMP_LINESIZE); 840 } 841#endif 842 843 dst = linebuf; 844 dst_end = dst + LCD_WIDTH; 845 gy = y - _grey_info.y; 846 gx = -_grey_info.x; 847 848#if LCD_PIXELFORMAT == HORIZONTAL_PACKING 849 gsrc = _grey_info.values + _GREY_MULUQ(_grey_info.width, gy); 850 851#if LCD_DEPTH == 2 852 src = lcd_fb + _GREY_MULUQ(LCD_FBWIDTH, y); 853 854 do 855 { 856 if (((unsigned)gy < (unsigned)_grey_info.height) 857 && ((unsigned)gx < (unsigned)_grey_info.width)) 858 { 859 *dst++ = *gsrc++; 860 *dst++ = *gsrc++; 861 *dst++ = *gsrc++; 862 *dst++ = *gsrc++; 863 } 864 else 865 { 866 unsigned data = *src; 867 *dst++ = colorindex[(data >> 6) & 3]; 868 *dst++ = colorindex[(data >> 4) & 3]; 869 *dst++ = colorindex[(data >> 2) & 3]; 870 *dst++ = colorindex[data & 3]; 871 } 872 gx++, src++; 873 } 874 while (dst < dst_end); 875 876#endif /* LCD_DEPTH */ 877#elif LCD_PIXELFORMAT == VERTICAL_PACKING 878 gsrc = _grey_info.values + (~gy & _GREY_BMASK) 879 + _GREY_MULUQ(_grey_info.width, gy & ~_GREY_BMASK); 880 881#if LCD_DEPTH == 1 882 mask = BIT_N(y & 7); 883 src = lcd_fb + _GREY_MULUQ(LCD_WIDTH, y >> 3); 884 885 do 886 { 887 if (((unsigned)gy < (unsigned)_grey_info.height) 888 && ((unsigned)gx < (unsigned)_grey_info.width)) 889 { 890 val = *gsrc; 891#ifdef HAVE_LCD_SPLIT 892 val -= val >> 7; 893#endif 894 gsrc += _GREY_BSIZE; 895 } 896 else 897 { 898#ifdef HAVE_NEGATIVE_LCD 899 val = (*src & mask) ? (NUM_SHADES-1) : 0; 900#else 901 val = (*src & mask) ? 0 : (NUM_SHADES-1); 902#endif 903 } 904#ifdef HAVE_LCD_SPLIT 905 if (y < LCD_SPLIT_POS) 906 val |= 0x80; 907#endif 908 *dst++ = val; 909 gx++, src++; 910 } 911 while (dst < dst_end); 912 913#elif LCD_DEPTH == 2 914 shift = 2 * (y & 3); 915 src = lcd_fb + _GREY_MULUQ(LCD_WIDTH, y >> 2); 916 917 do 918 { 919 if (((unsigned)gy < (unsigned)_grey_info.height) 920 && ((unsigned)gx < (unsigned)_grey_info.width)) 921 { 922 *dst++ = *gsrc; 923 gsrc += _GREY_BSIZE; 924 } 925 else 926 { 927 *dst++ = colorindex[(*src >> shift) & 3]; 928 } 929 gx++, src++; 930 } 931 while (dst < dst_end); 932 933#endif /* LCD_DEPTH */ 934#elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED 935 gsrc = _grey_info.values + (~gy & _GREY_BMASK) 936 + _GREY_MULUQ(_grey_info.width, gy & ~_GREY_BMASK); 937 938#if LCD_DEPTH == 2 939 shift = y & 7; 940 src = lcd_fb + _GREY_MULUQ(LCD_WIDTH, y >> 3); 941 942 do 943 { 944 if (((unsigned)gy < (unsigned)_grey_info.height) 945 && ((unsigned)gx < (unsigned)_grey_info.width)) 946 { 947 *dst++ = *gsrc; 948 gsrc += _GREY_BSIZE; 949 } 950 else 951 { 952 data = (*src >> shift) & 0x0101; 953 *dst++ = colorindex[((data >> 7) | data) & 3]; 954 } 955 gx++, src++; 956 } 957 while (dst < dst_end); 958 959#endif /* LCD_DEPTH */ 960#endif /* LCD_PIXELFORMAT */ 961 962 rb->write(fd, linebuf, BMP_LINESIZE); 963 } 964}