Revision 0:c546b51ecf0b, committed 2011-10-11
- Comitter:
- XkLi
- Date:
- Tue Oct 11 01:24:18 2011 +0000
- Commit message:
- v1.0
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FATFileSystem.lib Tue Oct 11 01:24:18 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_unsupported/code/fatfilesystem/
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/MPR121/mpr121.cpp Tue Oct 11 01:24:18 2011 +0000
@@ -0,0 +1,222 @@
+/*
+Copyright (c) 2011 Anthony Buckton (abuckton [at] blackink [dot} net {dot} au)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <mbed.h>
+#include <sstream>
+#include <string>
+#include <list>
+
+#include <mpr121.h>
+
+Mpr121::Mpr121(I2C *i2c, Address i2cAddress)
+{
+ this->i2c = i2c;
+
+ address = i2cAddress;
+
+ // Configure the MPR121 settings to default
+
+ this->configureSettings();
+}
+
+
+void Mpr121::configureSettings()
+{
+ // Put the MPR into setup mode
+ this->write(ELE_CFG,0x00);
+
+ // Electrode filters for when data is > baseline
+ unsigned char gtBaseline[] = {
+ 0x01, //MHD_R
+ 0x01, //NHD_R
+ 0x00, //NCL_R
+ 0x00 //FDL_R
+ };
+
+ writeMany(MHD_R,gtBaseline,4);
+
+ // Electrode filters for when data is < baseline
+ unsigned char ltBaseline[] = {
+ 0x01, //MHD_F
+ 0x01, //NHD_F
+ 0xFF, //NCL_F
+ 0x02 //FDL_F
+ };
+
+ writeMany(MHD_F,ltBaseline,4);
+
+ // Electrode touch and release thresholds
+ unsigned char electrodeThresholds[] = {
+ E_THR_T, // Touch Threshhold
+ E_THR_R // Release Threshold
+ };
+
+ for(int i=0; i<12; i++){
+ int result = writeMany((ELE0_T+(i*2)),electrodeThresholds,2);
+ }
+
+ // Proximity Settings
+ unsigned char proximitySettings[] = {
+ 0xff, //MHD_Prox_R
+ 0xff, //NHD_Prox_R
+ 0x00, //NCL_Prox_R
+ 0x00, //FDL_Prox_R
+ 0x01, //MHD_Prox_F
+ 0x01, //NHD_Prox_F
+ 0xFF, //NCL_Prox_F
+ 0xff, //FDL_Prox_F
+ 0x00, //NHD_Prox_T
+ 0x00, //NCL_Prox_T
+ 0x00 //NFD_Prox_T
+ };
+ writeMany(MHDPROXR,proximitySettings,11);
+
+ unsigned char proxThresh[] = {
+ PROX_THR_T, // Touch Threshold
+ PROX_THR_R // Release Threshold
+ };
+ writeMany(EPROXTTH,proxThresh,2);
+
+ this->write(FIL_CFG,0x04);
+
+ // Set the electrode config to transition to active mode
+ this->write(ELE_CFG,0x0c);
+}
+
+void Mpr121::setElectrodeThreshold(int electrode, unsigned char touch, unsigned char release){
+
+ if(electrode > 11) return;
+
+ // Get the current mode
+ unsigned char mode = this->read(ELE_CFG);
+
+ // Put the MPR into setup mode
+ this->write(ELE_CFG,0x00);
+
+ // Write the new threshold
+ this->write((ELE0_T+(electrode*2)), touch);
+ this->write((ELE0_T+(electrode*2)+1), release);
+
+ //Restore the operating mode
+ this->write(ELE_CFG, mode);
+}
+
+
+unsigned char Mpr121::read(int key){
+
+ unsigned char data[2];
+
+ //Start the command
+ i2c->start();
+
+ // Address the target (Write mode)
+ int ack1= i2c->write(address);
+
+ // Set the register key to read
+ int ack2 = i2c->write(key);
+
+ // Re-start for read of data
+ i2c->start();
+
+ // Re-send the target address in read mode
+ int ack3 = i2c->write(address+1);
+
+ // Read in the result
+ data[0] = i2c->read(0);
+
+ // Reset the bus
+ i2c->stop();
+
+ return data[0];
+}
+
+
+int Mpr121::write(int key, unsigned char value){
+
+ //Start the command
+ i2c->start();
+
+ // Address the target (Write mode)
+ int ack1= i2c->write(address);
+
+ // Set the register key to write
+ int ack2 = i2c->write(key);
+
+ // Read in the result
+ int ack3 = i2c->write(value);
+
+ // Reset the bus
+ i2c->stop();
+
+ return (ack1+ack2+ack3)-3;
+}
+
+
+int Mpr121::writeMany(int start, unsigned char* dataSet, int length){
+ //Start the command
+ i2c->start();
+
+ // Address the target (Write mode)
+ int ack= i2c->write(address);
+ if(ack!=1){
+ return -1;
+ }
+
+ // Set the register key to write
+ ack = i2c->write(start);
+ if(ack!=1){
+ return -1;
+ }
+
+ // Write the date set
+ int count = 0;
+ while(ack==1 && (count < length)){
+ ack = i2c->write(dataSet[count]);
+ count++;
+ }
+ // Stop the cmd
+ i2c->stop();
+
+ return count;
+}
+
+
+bool Mpr121::getProximityMode(){
+ if(this->read(ELE_CFG) > 0x0c)
+ return true;
+ else
+ return false;
+}
+
+void Mpr121::setProximityMode(bool mode){
+ this->write(ELE_CFG,0x00);
+ if(mode){
+ this->write(ELE_CFG,0x30); //Sense proximity from ALL pads
+ } else {
+ this->write(ELE_CFG,0x0c); //Sense touch, all 12 pads active.
+ }
+}
+
+
+int Mpr121::readTouchData(){
+ return this->read(0x00);
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/MPR121/mpr121.h Tue Oct 11 01:24:18 2011 +0000
@@ -0,0 +1,157 @@
+/*
+Copyright (c) 2011 Anthony Buckton (abuckton [at] blackink [dot} net {dot} au)
+
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+ Parts written by Jim Lindblom of Sparkfun
+ Ported to mbed by A.Buckton, Feb 2011
+*/
+
+#ifndef MPR121_H
+#define MPR121_H
+
+//using namespace std;
+
+class Mpr121
+{
+
+public:
+ // i2c Addresses, bit-shifted
+ enum Address { ADD_VSS = 0xb4,// ADD->VSS = 0x5a <-wiring on Sparkfun board
+ ADD_VDD = 0xb6,// ADD->VDD = 0x5b
+ ADD_SCL = 0xb8,// ADD->SDA = 0x5c
+ ADD_SDA = 0xba // ADD->SCL = 0x5d
+ };
+
+ // Real initialiser, takes the i2c address of the device.
+ Mpr121(I2C *i2c, Address i2cAddress);
+
+ bool getProximityMode();
+
+ void setProximityMode(bool mode);
+
+ int readTouchData();
+
+ unsigned char read(int key);
+
+ int write(int address, unsigned char value);
+ int writeMany(int start, unsigned char* dataSet, int length);
+
+ void setElectrodeThreshold(int electrodeId, unsigned char touchThreshold, unsigned char releaseThreshold);
+ void configureSettings();
+protected:
+ // Configures the MPR with standard settings. This is permitted to be overwritten by sub-classes.
+ //void configureSettings();
+
+private:
+ // The I2C bus instance.
+ I2C *i2c;
+
+ // i2c address of this mpr121
+ Address address;
+};
+
+
+// MPR121 Register Defines
+#define MHD_R 0x2B
+#define NHD_R 0x2C
+#define NCL_R 0x2D
+#define FDL_R 0x2E
+#define MHD_F 0x2F
+#define NHD_F 0x30
+#define NCL_F 0x31
+#define FDL_F 0x32
+#define NHDT 0x33
+#define NCLT 0x34
+#define FDLT 0x35
+// Proximity sensing controls
+#define MHDPROXR 0x36
+#define NHDPROXR 0x37
+#define NCLPROXR 0x38
+#define FDLPROXR 0x39
+#define MHDPROXF 0x3A
+#define NHDPROXF 0x3B
+#define NCLPROXF 0x3C
+#define FDLPROXF 0x3D
+#define NHDPROXT 0x3E
+#define NCLPROXT 0x3F
+#define FDLPROXT 0x40
+// Electrode Touch/Release thresholds
+#define ELE0_T 0x41
+#define ELE0_R 0x42
+#define ELE1_T 0x43
+#define ELE1_R 0x44
+#define ELE2_T 0x45
+#define ELE2_R 0x46
+#define ELE3_T 0x47
+#define ELE3_R 0x48
+#define ELE4_T 0x49
+#define ELE4_R 0x4A
+#define ELE5_T 0x4B
+#define ELE5_R 0x4C
+#define ELE6_T 0x4D
+#define ELE6_R 0x4E
+#define ELE7_T 0x4F
+#define ELE7_R 0x50
+#define ELE8_T 0x51
+#define ELE8_R 0x52
+#define ELE9_T 0x53
+#define ELE9_R 0x54
+#define ELE10_T 0x55
+#define ELE10_R 0x56
+#define ELE11_T 0x57
+#define ELE11_R 0x58
+// Proximity Touch/Release thresholds
+#define EPROXTTH 0x59
+#define EPROXRTH 0x5A
+// Debounce configuration
+#define DEB_CFG 0x5B
+// AFE- Analogue Front End configuration
+#define AFE_CFG 0x5C
+// Filter configuration
+#define FIL_CFG 0x5D
+// Electrode configuration - transistions to "active mode"
+#define ELE_CFG 0x5E
+
+#define GPIO_CTRL0 0x73
+#define GPIO_CTRL1 0x74
+#define GPIO_DATA 0x75
+#define GPIO_DIR 0x76
+#define GPIO_EN 0x77
+#define GPIO_SET 0x78
+#define GPIO_CLEAR 0x79
+#define GPIO_TOGGLE 0x7A
+// Auto configration registers
+#define AUTO_CFG_0 0x7B
+#define AUTO_CFG_U 0x7D
+#define AUTO_CFG_L 0x7E
+#define AUTO_CFG_T 0x7F
+
+// Threshold defaults
+// Electrode touch threshold
+#define E_THR_T 0x0F
+// Electrode release threshold
+#define E_THR_R 0x0A
+// Prox touch threshold
+#define PROX_THR_T 0x02
+// Prox release threshold
+#define PROX_THR_R 0x02
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/NokiaLCD/NokiaLCD.cpp Tue Oct 11 01:24:18 2011 +0000
@@ -0,0 +1,458 @@
+/* mbed Nokia LCD Library
+ * Copyright (c) 2007-2010, sford
+ */
+
+#include "NokiaLCD.h"
+
+#include "mbed.h"
+
+#define NOKIALCD_ROWS 16
+#define NOKIALCD_COLS 16
+#define NOKIALCD_WIDTH 130
+#define NOKIALCD_HEIGHT 130
+#define NOKIALCD_FREQUENCY 5000000
+
+NokiaLCD::NokiaLCD(PinName mosi, PinName sclk, PinName cs, PinName rst, LCDType type)
+ : _spi(mosi, NC, sclk)
+ , _rst(rst)
+ , _cs(cs) {
+
+ _type = type;
+
+ _row = 0;
+ _column = 0;
+ _foreground = 0x00FFFFFF;
+ _background = 0x00000000;
+
+ reset();
+}
+
+void NokiaLCD::reset() {
+
+ // setup the SPI interface and bring display out of reset
+ _cs = 1;
+ _rst = 0;
+ _spi.format(9);
+ _spi.frequency(NOKIALCD_FREQUENCY);
+ wait_ms(1);
+ _rst = 1;
+ wait_ms(1);
+
+ _cs = 0;
+
+ switch (_type) {
+ case LCD6100:
+ command(0xCA); // display control
+ data(0);
+ data(32);
+ data(0);
+ command(0xBB);
+ data(1);
+ command(0xD1); // oscillator on
+ command(0x94); // sleep out
+ command(0x20); // power control
+ data(0x0F);
+ command(0xA7); // invert display
+ command(0x81); // Voltage control
+ data(39); // contrast setting: 0..63
+ data(3); // resistance ratio
+ wait_ms(1);
+ command(0xBC);
+ data(0);
+ data(1);
+ data(4);
+ command(0xAF); // turn on the display
+ break;
+
+ case LCD6610:
+ command(0xCA); // display control
+ data(0);
+ data(31);
+ data(0);
+ command(0xBB);
+ data(1);
+ command(0xD1); // oscillator on
+ command(0x94); // sleep out
+ command(0x20); // power control
+ data(0x0F);
+ command(0xA7); // invert display
+ command(0x81); // Voltage control
+ data(39); // contrast setting: 0..63
+ data(3); // resistance ratio
+ wait_ms(1);
+ command(0xBC);
+ data(0);
+ data(0);
+ data(2);
+ command(0xAF); // turn on the display
+ break;
+
+ case PCF8833:
+ command(0x11); // sleep out
+ command(0x3A); // column mode
+ data(0x05);
+ command(0x36); // madctl
+ data(0x60); // vertical RAM, flip x
+ command(0x25); // setcon
+ data(0x30);// contrast 0x30
+ wait_ms(2);
+ command(0x29);//DISPON
+ command(0x03);//BSTRON
+ break;
+ }
+
+ _cs = 1;
+
+ cls();
+}
+
+void NokiaLCD::command(int value) {
+ _spi.write(value & 0xFF);
+}
+
+void NokiaLCD::data(int value) {
+ _spi.write(value | 0x100);
+}
+
+void NokiaLCD::_window(int x, int y, int width, int height) {
+ int x1 = x + 0;
+ int y1 = y + 0;
+ int x2 = x1 + width - 1;
+ int y2 = y1 + height - 1;
+
+ switch (_type) {
+ case LCD6100:
+ case LCD6610:
+ command(0x15); // column
+ data(x1);
+ data(x2);
+ command(0x75); // row
+ data(y1);
+ data(y2);
+ command(0x5C); // start write to ram
+ break;
+ case PCF8833:
+ command(0x2A); // column
+ data(x1);
+ data(x2);
+ command(0x2B); // row
+ data(y1);
+ data(y2);
+ command(0x2C); // start write to ram
+ break;
+ }
+}
+
+void NokiaLCD::_putp(int colour) {
+ int gr = ((colour >> 20) & 0x0F)
+ | ((colour >> 8 ) & 0xF0);
+ int nb = ((colour >> 4 ) & 0x0F);
+ data(nb);
+ data(gr);
+}
+
+const unsigned char FONT8x8[97][8] = {
+ 0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00, // columns, rows, num_bytes_per_char
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // space 0x20
+ 0x30,0x78,0x78,0x30,0x30,0x00,0x30,0x00, // !
+ 0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00, // "
+ 0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00, // #
+ 0x18,0x3E,0x60,0x3C,0x06,0x7C,0x18,0x00, // $
+ 0x00,0x63,0x66,0x0C,0x18,0x33,0x63,0x00, // %
+ 0x1C,0x36,0x1C,0x3B,0x6E,0x66,0x3B,0x00, // &
+ 0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00, // '
+ 0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00, // (
+ 0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00, // )
+ 0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00, // *
+ 0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00, // +
+ 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30, // ,
+ 0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00, // -
+ 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00, // .
+ 0x03,0x06,0x0C,0x18,0x30,0x60,0x40,0x00, // / (forward slash)
+ 0x3E,0x63,0x63,0x6B,0x63,0x63,0x3E,0x00, // 0 0x30
+ 0x18,0x38,0x58,0x18,0x18,0x18,0x7E,0x00, // 1
+ 0x3C,0x66,0x06,0x1C,0x30,0x66,0x7E,0x00, // 2
+ 0x3C,0x66,0x06,0x1C,0x06,0x66,0x3C,0x00, // 3
+ 0x0E,0x1E,0x36,0x66,0x7F,0x06,0x0F,0x00, // 4
+ 0x7E,0x60,0x7C,0x06,0x06,0x66,0x3C,0x00, // 5
+ 0x1C,0x30,0x60,0x7C,0x66,0x66,0x3C,0x00, // 6
+ 0x7E,0x66,0x06,0x0C,0x18,0x18,0x18,0x00, // 7
+ 0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00, // 8
+ 0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00, // 9
+ 0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00, // :
+ 0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x30, // ;
+ 0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00, // <
+ 0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00, // =
+ 0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00, // >
+ 0x3C,0x66,0x06,0x0C,0x18,0x00,0x18,0x00, // ?
+ 0x3E,0x63,0x6F,0x69,0x6F,0x60,0x3E,0x00, // @ 0x40
+ 0x18,0x3C,0x66,0x66,0x7E,0x66,0x66,0x00, // A
+ 0x7E,0x33,0x33,0x3E,0x33,0x33,0x7E,0x00, // B
+ 0x1E,0x33,0x60,0x60,0x60,0x33,0x1E,0x00, // C
+ 0x7C,0x36,0x33,0x33,0x33,0x36,0x7C,0x00, // D
+ 0x7F,0x31,0x34,0x3C,0x34,0x31,0x7F,0x00, // E
+ 0x7F,0x31,0x34,0x3C,0x34,0x30,0x78,0x00, // F
+ 0x1E,0x33,0x60,0x60,0x67,0x33,0x1F,0x00, // G
+ 0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00, // H
+ 0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00, // I
+ 0x0F,0x06,0x06,0x06,0x66,0x66,0x3C,0x00, // J
+ 0x73,0x33,0x36,0x3C,0x36,0x33,0x73,0x00, // K
+ 0x78,0x30,0x30,0x30,0x31,0x33,0x7F,0x00, // L
+ 0x63,0x77,0x7F,0x7F,0x6B,0x63,0x63,0x00, // M
+ 0x63,0x73,0x7B,0x6F,0x67,0x63,0x63,0x00, // N
+ 0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00, // O
+ 0x7E,0x33,0x33,0x3E,0x30,0x30,0x78,0x00, // P 0x50
+ 0x3C,0x66,0x66,0x66,0x6E,0x3C,0x0E,0x00, // Q
+ 0x7E,0x33,0x33,0x3E,0x36,0x33,0x73,0x00, // R
+ 0x3C,0x66,0x30,0x18,0x0C,0x66,0x3C,0x00, // S
+ 0x7E,0x5A,0x18,0x18,0x18,0x18,0x3C,0x00, // T
+ 0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x00, // U
+ 0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00, // V
+ 0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x00, // W
+ 0x63,0x63,0x36,0x1C,0x1C,0x36,0x63,0x00, // X
+ 0x66,0x66,0x66,0x3C,0x18,0x18,0x3C,0x00, // Y
+ 0x7F,0x63,0x46,0x0C,0x19,0x33,0x7F,0x00, // Z
+ 0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00, // [
+ 0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0x00, // \ (back slash)
+ 0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00, // ]
+ 0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00, // ^
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF, // _
+ 0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00, // ` 0x60
+ 0x00,0x00,0x3C,0x06,0x3E,0x66,0x3B,0x00, // a
+ 0x70,0x30,0x3E,0x33,0x33,0x33,0x6E,0x00, // b
+ 0x00,0x00,0x3C,0x66,0x60,0x66,0x3C,0x00, // c
+ 0x0E,0x06,0x3E,0x66,0x66,0x66,0x3B,0x00, // d
+ 0x00,0x00,0x3C,0x66,0x7E,0x60,0x3C,0x00, // e
+ 0x1C,0x36,0x30,0x78,0x30,0x30,0x78,0x00, // f
+ 0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x7C, // g
+ 0x70,0x30,0x36,0x3B,0x33,0x33,0x73,0x00, // h
+ 0x18,0x00,0x38,0x18,0x18,0x18,0x3C,0x00, // i
+ 0x06,0x00,0x06,0x06,0x06,0x66,0x66,0x3C, // j
+ 0x70,0x30,0x33,0x36,0x3C,0x36,0x73,0x00, // k
+ 0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00, // l
+ 0x00,0x00,0x66,0x7F,0x7F,0x6B,0x63,0x00, // m
+ 0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x00, // n
+ 0x00,0x00,0x3C,0x66,0x66,0x66,0x3C,0x00, // o
+ 0x00,0x00,0x6E,0x33,0x33,0x3E,0x30,0x78, // p
+ 0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x0F, // q
+ 0x00,0x00,0x6E,0x3B,0x33,0x30,0x78,0x00, // r
+ 0x00,0x00,0x3E,0x60,0x3C,0x06,0x7C,0x00, // s
+ 0x08,0x18,0x3E,0x18,0x18,0x1A,0x0C,0x00, // t
+ 0x00,0x00,0x66,0x66,0x66,0x66,0x3B,0x00, // u
+ 0x00,0x00,0x66,0x66,0x66,0x3C,0x18,0x00, // v
+ 0x00,0x00,0x63,0x6B,0x7F,0x7F,0x36,0x00, // w
+ 0x00,0x00,0x63,0x36,0x1C,0x36,0x63,0x00, // x
+ 0x00,0x00,0x66,0x66,0x66,0x3E,0x06,0x7C, // y
+ 0x00,0x00,0x7E,0x4C,0x18,0x32,0x7E,0x00, // z
+ 0x0E,0x18,0x18,0x70,0x18,0x18,0x0E,0x00, // {
+ 0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x0C,0x00, // |
+ 0x70,0x18,0x18,0x0E,0x18,0x18,0x70,0x00, // }
+ 0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00, // ~
+ 0x1C,0x36,0x36,0x1C,0x00,0x00,0x00,0x00
+}; // DEL
+
+void NokiaLCD::locate(int column, int row) {
+ _column = column;
+ _row = row;
+}
+
+void NokiaLCD::newline() {
+ _column = 0;
+ _row++;
+ if (_row >= _rows) {
+ _row = 0;
+ }
+}
+
+int NokiaLCD::_putc(int value) {
+ int x = _column * 8; // FIXME: Char sizes
+ int y = _row * 8;
+ bitblit(x + 1, y + 1, 8, 8, (char*)&(FONT8x8[value - 0x1F][0]));
+
+ _column++;
+
+ if (_column >= NOKIALCD_COLS) {
+ _row++;
+ _column = 0;
+ }
+
+ if (_row >= NOKIALCD_ROWS) {
+ _row = 0;
+ }
+
+ return value;
+}
+
+void NokiaLCD::cls() {
+ fill(0, 0, NOKIALCD_WIDTH, NOKIALCD_HEIGHT, _background);
+ _row = 0;
+ _column = 0;
+}
+
+
+void NokiaLCD::window(int x, int y, int width, int height) {
+ _cs = 0;
+ _window(x, y, width, height);
+ _cs = 1;
+}
+
+void NokiaLCD::putp(int colour) {
+ _cs = 0;
+ _putp(colour);
+ _cs = 1;
+}
+
+void NokiaLCD::pixel(int x, int y, int colour) {
+ _cs = 0;
+ _window(x, y, 1, 1);
+ switch (_type) {
+ case LCD6100:
+ case PCF8833:
+
+ _putp(colour);
+
+ break;
+ case LCD6610:
+
+ int r4 = (colour >> (16 + 4)) & 0xF;
+ int g4 = (colour >> (8 + 4)) & 0xF;
+ int b4 = (colour >> (0 + 4)) & 0xF;
+ int d1 = (r4 << 4) | g4;
+ int d2 = (b4 << 4) | r4;
+ int d3 = (g4 << 4) | b4;
+ data(d1);
+ data(d2);
+ data(d3);
+
+ break;
+ }
+ _cs = 1;
+}
+
+void NokiaLCD::fill(int x, int y, int width, int height, int colour) {
+ _cs = 0;
+ _window(x, y, width, height);
+ switch (_type) {
+ case LCD6100:
+ case PCF8833:
+ for (int i=0; i<width*height; i++) {
+ _putp(colour);
+ }
+ break;
+ case LCD6610:
+ for (int i=0; i<width*height/2; i++) {
+ int r4 = (colour >> (16 + 4)) & 0xF;
+ int g4 = (colour >> (8 + 4)) & 0xF;
+ int b4 = (colour >> (0 + 4)) & 0xF;
+ int d1 = (r4 << 4) | g4;
+ int d2 = (b4 << 4) | r4;
+ int d3 = (g4 << 4) | b4;
+ data(d1);
+ data(d2);
+ data(d3);
+ }
+ break;
+ }
+ _window(0, 0, NOKIALCD_WIDTH, NOKIALCD_HEIGHT);
+ _cs = 1;
+}
+
+void NokiaLCD::blit(int x, int y, int width, int height, const int* colour) {
+ _cs = 0;
+ _window(x, y, width, height);
+
+ switch (_type) {
+ case LCD6100:
+ case PCF8833:
+ for (int i=0; i<width*height; i++) {
+ _putp(colour[i]);
+ }
+ break;
+ case LCD6610:
+ for (int i=0; i<width*height/2; i++) {
+ int r41 = (colour[i*2] >> (16 + 4)) & 0xF;
+ int g41 = (colour[i*2] >> (8 + 4)) & 0xF;
+ int b41 = (colour[i*2] >> (0 + 4)) & 0xF;
+
+ int r42 = (colour[i*2+1] >> (16 + 4)) & 0xF;
+ int g42 = (colour[i*2+1] >> (8 + 4)) & 0xF;
+ int b42 = (colour[i*2+1] >> (0 + 4)) & 0xF;
+ int d1 = (r41 << 4) | g41;
+ int d2 = (b41 << 4) | r42;
+ int d3 = (g42 << 4) | b42;
+ data(d1);
+ data(d2);
+ data(d3);
+ }
+ break;
+ }
+ _window(0, 0, NOKIALCD_WIDTH, NOKIALCD_HEIGHT);
+ _cs = 1;
+}
+
+void NokiaLCD::bitblit(int x, int y, int width, int height, const char* bitstream) {
+ _cs = 0;
+ _window(x, y, width, height);
+
+ switch (_type) {
+ case LCD6100:
+ case PCF8833:
+ for (int i=0; i<height*width; i++) {
+ int byte = i / 8;
+ int bit = i % 8;
+ int colour = ((bitstream[byte] << bit) & 0x80) ? _foreground : _background;
+ _putp(colour);
+ }
+ break;
+ case LCD6610:
+ for(int i=0; i<height*width/2; i++) {
+ int byte1 = (i*2) / 8;
+ int bit1 = (i*2) % 8;
+ int colour1 = ((bitstream[byte1] << bit1) & 0x80) ? _foreground : _background;
+ int byte2 = (i*2+1) / 8;
+ int bit2 = (i*2+1) % 8;
+ int colour2 = ((bitstream[byte2] << bit2) & 0x80) ? _foreground : _background;
+
+ int r41 = (colour1 >> (16 + 4)) & 0xF;
+ int g41 = (colour1 >> (8 + 4)) & 0xF;
+ int b41 = (colour1 >> (0 + 4)) & 0xF;
+
+ int r42 = (colour2 >> (16 + 4)) & 0xF;
+ int g42 = (colour2 >> (8 + 4)) & 0xF;
+ int b42 = (colour2 >> (0 + 4)) & 0xF;
+ int d1 = (r41 << 4) | g41;
+ int d2 = (b41 << 4) | r42;
+ int d3 = (g42 << 4) | b42;
+ data(d1);
+ data(d2);
+ data(d3);
+ }
+ break;
+ }
+ _window(0, 0, _width, _height);
+ _cs = 1;
+}
+
+void NokiaLCD::foreground(int c) {
+ _foreground = c;
+}
+
+void NokiaLCD::background(int c) {
+ _background = c;
+}
+
+int NokiaLCD::width() {
+ return NOKIALCD_WIDTH;
+}
+
+int NokiaLCD::height() {
+ return NOKIALCD_HEIGHT;
+}
+
+int NokiaLCD::columns() {
+ return NOKIALCD_COLS;
+}
+
+int NokiaLCD::rows() {
+ return NOKIALCD_ROWS;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/NokiaLCD/NokiaLCD.h Tue Oct 11 01:24:18 2011 +0000
@@ -0,0 +1,151 @@
+/* mbed NokiaLCD Library, for a 130x130 Nokia colour LCD
+ * Copyright (c) 2007-2010, sford
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MBED_NOKIALCD_H
+#define MBED_NOKIALCD_H
+
+#include "mbed.h"
+
+/** An interface for the 130x130 Nokia Mobile phone screens
+ *
+ * @code
+ * #include "mbed.h"
+ * #include "NokiaLCD.h"
+ *
+ * NokiaLCD lcd(p5, p7, p8, p9, NokiaLCD::6610); // mosi, sclk, cs, rst, type
+ *
+ * int main() {
+ * lcd.printf("Hello World!");
+ * }
+ * @endcode
+ */
+class NokiaLCD : public Stream {
+
+public:
+ /** LCD panel format */
+ enum LCDType {
+ LCD6100 /**< Nokia 6100, as found on sparkfun board (default) */
+ , LCD6610 /**< Nokia 6610, as found on olimex board */
+ , PCF8833
+ };
+
+ /** Create and Nokia LCD interface, using a SPI and two DigitalOut interfaces
+ *
+ * @param mosi SPI data out
+ * @param sclk SPI clock
+ * @param cs Chip Select (DigitalOut)
+ * @param rst Reset (DigitalOut)
+ * @param type The LCDType to select driver chip variants
+ */
+ NokiaLCD(PinName mosi, PinName sclk, PinName cs, PinName rst, LCDType type = LCD6100);
+
+#if DOXYGEN_ONLY
+ /** Write a character to the LCD
+ *
+ * @param c The character to write to the display
+ */
+ int putc(int c);
+
+ /** Write a formated string to the LCD
+ *
+ * @param format A printf-style format string, followed by the
+ * variables to use in formating the string.
+ */
+ int printf(const char* format, ...);
+#endif
+
+ /** Locate to a screen column and row
+ *
+ * @param column The horizontal position from the left, indexed from 0
+ * @param row The vertical position from the top, indexed from 0
+ */
+ void locate(int column, int row);
+
+ /** Clear the screen and locate to 0,0 */
+ void cls();
+
+ /** Set a pixel on te screen
+ *
+ * @param x horizontal position from left
+ * @param y vertical position from top
+ * @param colour 24-bit colour in format 0x00RRGGBB
+ */
+ void pixel(int x, int y, int colour);
+
+ /** Fill an area of the screen
+ *
+ * @param x horizontal position from left
+ * @param y vertical position from top
+ * @param width width in pixels
+ * @param height height in pixels
+ * @param colour 24-bit colour in format 0x00RRGGBB
+ */
+ void fill(int x, int y, int width, int height, int colour);
+
+ void blit(int x, int y, int width, int height, const int* colour);
+ void bitblit(int x, int y, int width, int height, const char* bitstream);
+
+ int width();
+ int height();
+ int columns();
+ int rows();
+
+ void reset();
+
+ /** Set the foreground colour
+ *
+ * @param c 24-bit colour
+ */
+ void foreground(int c);
+
+ /** Set the background colour
+ *
+ * @param c 24-bit colour
+ */
+ void background(int c);
+
+protected:
+ virtual void _window(int x, int y, int width, int height);
+ virtual void _putp(int colour);
+
+ void command(int value);
+ void data(int value);
+
+ void newline();
+ virtual int _putc(int c);
+ virtual int _getc() {
+ return 0;
+ }
+ void putp(int v);
+ void window(int x, int y, int width, int height);
+
+ SPI _spi;
+ DigitalOut _rst;
+ DigitalOut _cs;
+
+ LCDType _type;
+ int _row, _column, _rows, _columns, _foreground, _background, _width, _height;
+};
+
+#endif
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/SDFileSystem/SDFileSystem.cpp Tue Oct 11 01:24:18 2011 +0000
@@ -0,0 +1,457 @@
+/* mbed SDFileSystem Library, for providing file access to SD cards
+ * Copyright (c) 2008-2010, sford
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/* Introduction
+ * ------------
+ * SD and MMC cards support a number of interfaces, but common to them all
+ * is one based on SPI. This is the one I'm implmenting because it means
+ * it is much more portable even though not so performant, and we already
+ * have the mbed SPI Interface!
+ *
+ * The main reference I'm using is Chapter 7, "SPI Mode" of:
+ * http://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf
+ *
+ * SPI Startup
+ * -----------
+ * The SD card powers up in SD mode. The SPI interface mode is selected by
+ * asserting CS low and sending the reset command (CMD0). The card will
+ * respond with a (R1) response.
+ *
+ * CMD8 is optionally sent to determine the voltage range supported, and
+ * indirectly determine whether it is a version 1.x SD/non-SD card or
+ * version 2.x. I'll just ignore this for now.
+ *
+ * ACMD41 is repeatedly issued to initialise the card, until "in idle"
+ * (bit 0) of the R1 response goes to '0', indicating it is initialised.
+ *
+ * You should also indicate whether the host supports High Capicity cards,
+ * and check whether the card is high capacity - i'll also ignore this
+ *
+ * SPI Protocol
+ * ------------
+ * The SD SPI protocol is based on transactions made up of 8-bit words, with
+ * the host starting every bus transaction by asserting the CS signal low. The
+ * card always responds to commands, data blocks and errors.
+ *
+ * The protocol supports a CRC, but by default it is off (except for the
+ * first reset CMD0, where the CRC can just be pre-calculated, and CMD8)
+ * I'll leave the CRC off I think!
+ *
+ * Standard capacity cards have variable data block sizes, whereas High
+ * Capacity cards fix the size of data block to 512 bytes. I'll therefore
+ * just always use the Standard Capacity cards with a block size of 512 bytes.
+ * This is set with CMD16.
+ *
+ * You can read and write single blocks (CMD17, CMD25) or multiple blocks
+ * (CMD18, CMD25). For simplicity, I'll just use single block accesses. When
+ * the card gets a read command, it responds with a response token, and then
+ * a data token or an error.
+ *
+ * SPI Command Format
+ * ------------------
+ * Commands are 6-bytes long, containing the command, 32-bit argument, and CRC.
+ *
+ * +---------------+------------+------------+-----------+----------+--------------+
+ * | 01 | cmd[5:0] | arg[31:24] | arg[23:16] | arg[15:8] | arg[7:0] | crc[6:0] | 1 |
+ * +---------------+------------+------------+-----------+----------+--------------+
+ *
+ * As I'm not using CRC, I can fix that byte to what is needed for CMD0 (0x95)
+ *
+ * All Application Specific commands shall be preceded with APP_CMD (CMD55).
+ *
+ * SPI Response Format
+ * -------------------
+ * The main response format (R1) is a status byte (normally zero). Key flags:
+ * idle - 1 if the card is in an idle state/initialising
+ * cmd - 1 if an illegal command code was detected
+ *
+ * +-------------------------------------------------+
+ * R1 | 0 | arg | addr | seq | crc | cmd | erase | idle |
+ * +-------------------------------------------------+
+ *
+ * R1b is the same, except it is followed by a busy signal (zeros) until
+ * the first non-zero byte when it is ready again.
+ *
+ * Data Response Token
+ * -------------------
+ * Every data block written to the card is acknowledged by a byte
+ * response token
+ *
+ * +----------------------+
+ * | xxx | 0 | status | 1 |
+ * +----------------------+
+ * 010 - OK!
+ * 101 - CRC Error
+ * 110 - Write Error
+ *
+ * Single Block Read and Write
+ * ---------------------------
+ *
+ * Block transfers have a byte header, followed by the data, followed
+ * by a 16-bit CRC. In our case, the data will always be 512 bytes.
+ *
+ * +------+---------+---------+- - - -+---------+-----------+----------+
+ * | 0xFE | data[0] | data[1] | | data[n] | crc[15:8] | crc[7:0] |
+ * +------+---------+---------+- - - -+---------+-----------+----------+
+ */
+
+#include "SDFileSystem.h"
+
+#define SD_COMMAND_TIMEOUT 5000
+
+SDFileSystem::SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name) :
+ FATFileSystem(name), _spi(mosi, miso, sclk), _cs(cs) {
+ _cs = 1;
+}
+
+#define R1_IDLE_STATE (1 << 0)
+#define R1_ERASE_RESET (1 << 1)
+#define R1_ILLEGAL_COMMAND (1 << 2)
+#define R1_COM_CRC_ERROR (1 << 3)
+#define R1_ERASE_SEQUENCE_ERROR (1 << 4)
+#define R1_ADDRESS_ERROR (1 << 5)
+#define R1_PARAMETER_ERROR (1 << 6)
+
+// Types
+// - v1.x Standard Capacity
+// - v2.x Standard Capacity
+// - v2.x High Capacity
+// - Not recognised as an SD Card
+
+#define SDCARD_FAIL 0
+#define SDCARD_V1 1
+#define SDCARD_V2 2
+#define SDCARD_V2HC 3
+
+int SDFileSystem::initialise_card() {
+ // Set to 100kHz for initialisation, and clock card with cs = 1
+ _spi.frequency(100000);
+ _cs = 1;
+ for(int i=0; i<16; i++) {
+ _spi.write(0xFF);
+ }
+
+ // send CMD0, should return with all zeros except IDLE STATE set (bit 0)
+ if(_cmd(0, 0) != R1_IDLE_STATE) {
+ fprintf(stderr, "No disk, or could not put SD card in to SPI idle state\n");
+ return SDCARD_FAIL;
+ }
+
+ // send CMD8 to determine whther it is ver 2.x
+ int r = _cmd8();
+ if(r == R1_IDLE_STATE) {
+ return initialise_card_v2();
+ } else if(r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) {
+ return initialise_card_v1();
+ } else {
+ fprintf(stderr, "Not in idle state after sending CMD8 (not an SD card?)\n");
+ return SDCARD_FAIL;
+ }
+}
+
+int SDFileSystem::initialise_card_v1() {
+ for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
+ _cmd(55, 0);
+ if(_cmd(41, 0) == 0) {
+ return SDCARD_V1;
+ }
+ }
+
+ fprintf(stderr, "Timeout waiting for v1.x card\n");
+ return SDCARD_FAIL;
+}
+
+int SDFileSystem::initialise_card_v2() {
+
+ for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
+ _cmd(55, 0);
+ if(_cmd(41, 0) == 0) {
+ _cmd58();
+ return SDCARD_V2;
+ }
+ }
+
+ fprintf(stderr, "Timeout waiting for v2.x card\n");
+ return SDCARD_FAIL;
+}
+
+int SDFileSystem::disk_initialize() {
+
+ int i = initialise_card();
+// printf("init card = %d\n", i);
+// printf("OK\n");
+
+ _sectors = _sd_sectors();
+
+ // Set block length to 512 (CMD16)
+ if(_cmd(16, 512) != 0) {
+ fprintf(stderr, "Set 512-byte block timed out\n");
+ return 1;
+ }
+
+ _spi.frequency(1000000); // Set to 1MHz for data transfer
+ return 0;
+}
+
+int SDFileSystem::disk_write(const char *buffer, int block_number) {
+ // set write address for single block (CMD24)
+ if(_cmd(24, block_number * 512) != 0) {
+ return 1;
+ }
+
+ // send the data block
+ _write(buffer, 512);
+ return 0;
+}
+
+int SDFileSystem::disk_read(char *buffer, int block_number) {
+ // set read address for single block (CMD17)
+ if(_cmd(17, block_number * 512) != 0) {
+ return 1;
+ }
+
+ // receive the data
+ _read(buffer, 512);
+ return 0;
+}
+
+int SDFileSystem::disk_status() { return 0; }
+int SDFileSystem::disk_sync() { return 0; }
+int SDFileSystem::disk_sectors() { return _sectors; }
+
+// PRIVATE FUNCTIONS
+
+int SDFileSystem::_cmd(int cmd, int arg) {
+ _cs = 0;
+
+ // send a command
+ _spi.write(0x40 | cmd);
+ _spi.write(arg >> 24);
+ _spi.write(arg >> 16);
+ _spi.write(arg >> 8);
+ _spi.write(arg >> 0);
+ _spi.write(0x95);
+
+ // wait for the repsonse (response[7] == 0)
+ for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
+ int response = _spi.write(0xFF);
+ if(!(response & 0x80)) {
+ _cs = 1;
+ _spi.write(0xFF);
+ return response;
+ }
+ }
+ _cs = 1;
+ _spi.write(0xFF);
+ return -1; // timeout
+}
+int SDFileSystem::_cmdx(int cmd, int arg) {
+ _cs = 0;
+
+ // send a command
+ _spi.write(0x40 | cmd);
+ _spi.write(arg >> 24);
+ _spi.write(arg >> 16);
+ _spi.write(arg >> 8);
+ _spi.write(arg >> 0);
+ _spi.write(0x95);
+
+ // wait for the repsonse (response[7] == 0)
+ for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
+ int response = _spi.write(0xFF);
+ if(!(response & 0x80)) {
+ return response;
+ }
+ }
+ _cs = 1;
+ _spi.write(0xFF);
+ return -1; // timeout
+}
+
+
+int SDFileSystem::_cmd58() {
+ _cs = 0;
+ int arg = 0;
+
+ // send a command
+ _spi.write(0x40 | 58);
+ _spi.write(arg >> 24);
+ _spi.write(arg >> 16);
+ _spi.write(arg >> 8);
+ _spi.write(arg >> 0);
+ _spi.write(0x95);
+
+ // wait for the repsonse (response[7] == 0)
+ for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
+ int response = _spi.write(0xFF);
+ if(!(response & 0x80)) {
+ int ocr = _spi.write(0xFF) << 24;
+ ocr |= _spi.write(0xFF) << 16;
+ ocr |= _spi.write(0xFF) << 8;
+ ocr |= _spi.write(0xFF) << 0;
+// printf("OCR = 0x%08X\n", ocr);
+ _cs = 1;
+ _spi.write(0xFF);
+ return response;
+ }
+ }
+ _cs = 1;
+ _spi.write(0xFF);
+ return -1; // timeout
+}
+
+int SDFileSystem::_cmd8() {
+ _cs = 0;
+
+ // send a command
+ _spi.write(0x40 | 8); // CMD8
+ _spi.write(0x00); // reserved
+ _spi.write(0x00); // reserved
+ _spi.write(0x01); // 3.3v
+ _spi.write(0xAA); // check pattern
+ _spi.write(0x87); // crc
+
+ // wait for the repsonse (response[7] == 0)
+ for(int i=0; i<SD_COMMAND_TIMEOUT * 1000; i++) {
+ char response[5];
+ response[0] = _spi.write(0xFF);
+ if(!(response[0] & 0x80)) {
+ for(int j=1; j<5; j++) {
+ response[i] = _spi.write(0xFF);
+ }
+ _cs = 1;
+ _spi.write(0xFF);
+ return response[0];
+ }
+ }
+ _cs = 1;
+ _spi.write(0xFF);
+ return -1; // timeout
+}
+
+int SDFileSystem::_read(char *buffer, int length) {
+ _cs = 0;
+
+ // read until start byte (0xFF)
+ while(_spi.write(0xFF) != 0xFE);
+
+ // read data
+ for(int i=0; i<length; i++) {
+ buffer[i] = _spi.write(0xFF);
+ }
+ _spi.write(0xFF); // checksum
+ _spi.write(0xFF);
+
+ _cs = 1;
+ _spi.write(0xFF);
+ return 0;
+}
+
+int SDFileSystem::_write(const char *buffer, int length) {
+ _cs = 0;
+
+ // indicate start of block
+ _spi.write(0xFE);
+
+ // write the data
+ for(int i=0; i<length; i++) {
+ _spi.write(buffer[i]);
+ }
+
+ // write the checksum
+ _spi.write(0xFF);
+ _spi.write(0xFF);
+
+ // check the repsonse token
+ if((_spi.write(0xFF) & 0x1F) != 0x05) {
+ _cs = 1;
+ _spi.write(0xFF);
+ return 1;
+ }
+
+ // wait for write to finish
+ while(_spi.write(0xFF) == 0);
+
+ _cs = 1;
+ _spi.write(0xFF);
+ return 0;
+}
+
+static int ext_bits(char *data, int msb, int lsb) {
+ int bits = 0;
+ int size = 1 + msb - lsb;
+ for(int i=0; i<size; i++) {
+ int position = lsb + i;
+ int byte = 15 - (position >> 3);
+ int bit = position & 0x7;
+ int value = (data[byte] >> bit) & 1;
+ bits |= value << i;
+ }
+ return bits;
+}
+
+int SDFileSystem::_sd_sectors() {
+
+ // CMD9, Response R2 (R1 byte + 16-byte block read)
+ if(_cmdx(9, 0) != 0) {
+ fprintf(stderr, "Didn't get a response from the disk\n");
+ return 0;
+ }
+
+ char csd[16];
+ if(_read(csd, 16) != 0) {
+ fprintf(stderr, "Couldn't read csd response from disk\n");
+ return 0;
+ }
+
+ // csd_structure : csd[127:126]
+ // c_size : csd[73:62]
+ // c_size_mult : csd[49:47]
+ // read_bl_len : csd[83:80] - the *maximum* read block length
+
+ int csd_structure = ext_bits(csd, 127, 126);
+ int c_size = ext_bits(csd, 73, 62);
+ int c_size_mult = ext_bits(csd, 49, 47);
+ int read_bl_len = ext_bits(csd, 83, 80);
+
+// printf("CSD_STRUCT = %d\n", csd_structure);
+
+ if(csd_structure != 0) {
+ fprintf(stderr, "This disk tastes funny! I only know about type 0 CSD structures\n");
+ return 0;
+ }
+
+ // memory capacity = BLOCKNR * BLOCK_LEN
+ // where
+ // BLOCKNR = (C_SIZE+1) * MULT
+ // MULT = 2^(C_SIZE_MULT+2) (C_SIZE_MULT < 8)
+ // BLOCK_LEN = 2^READ_BL_LEN, (READ_BL_LEN < 12)
+
+ int block_len = 1 << read_bl_len;
+ int mult = 1 << (c_size_mult + 2);
+ int blocknr = (c_size + 1) * mult;
+ int capacity = blocknr * block_len;
+
+ int blocks = capacity / 512;
+
+ return blocks;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/SDFileSystem/SDFileSystem.h Tue Oct 11 01:24:18 2011 +0000
@@ -0,0 +1,81 @@
+/* mbed SDFileSystem Library, for providing file access to SD cards
+ * Copyright (c) 2008-2010, sford
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MBED_SDFILESYSTEM_H
+#define MBED_SDFILESYSTEM_H
+
+#include "mbed.h"
+#include "FATFileSystem.h"
+
+/** Access the filesystem on an SD Card using SPI
+ *
+ * @code
+ * #include "mbed.h"
+ * #include "SDFileSystem.h"
+ *
+ * SDFileSystem sd(p5, p6, p7, p12, "sd"); // mosi, miso, sclk, cs
+ *
+ * int main() {
+ * FILE *fp = fopen("/sd/myfile.txt", "w");
+ * fprintf(fp, "Hello World!\n");
+ * fclose(fp);
+ * }
+ */
+class SDFileSystem : public FATFileSystem {
+public:
+
+ /** Create the File System for accessing an SD Card using SPI
+ *
+ * @param mosi SPI mosi pin connected to SD Card
+ * @param miso SPI miso pin conencted to SD Card
+ * @param sclk SPI sclk pin connected to SD Card
+ * @param cs DigitalOut pin used as SD Card chip select
+ * @param name The name used to access the virtual filesystem
+ */
+ SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name);
+ virtual int disk_initialize();
+ virtual int disk_write(const char *buffer, int block_number);
+ virtual int disk_read(char *buffer, int block_number);
+ virtual int disk_status();
+ virtual int disk_sync();
+ virtual int disk_sectors();
+
+protected:
+
+ int _cmd(int cmd, int arg);
+ int _cmdx(int cmd, int arg);
+ int _cmd8();
+ int _cmd58();
+ int initialise_card();
+ int initialise_card_v1();
+ int initialise_card_v2();
+
+ int _read(char *buffer, int length);
+ int _write(const char *buffer, int length);
+ int _sd_sectors();
+ int _sectors;
+
+ SPI _spi;
+ DigitalOut _cs;
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Tue Oct 11 01:24:18 2011 +0000
@@ -0,0 +1,186 @@
+#include "mbed.h"
+#include "SDFileSystem.h"
+#include "NokiaLCD.h"
+#include "myBMP.h"
+#include "mpr121.h"
+#include "jpegutil.h"
+#include <string>
+#include <cctype>
+
+SDFileSystem sd(p5, p6, p7, p8, "sd");
+NokiaLCD lcd(p11, p13, p14, p15, NokiaLCD::LCD6610);
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+DigitalOut led3(LED3);
+DigitalOut led4(LED4);
+InterruptIn interrupt(p26);
+I2C i2c(p9,p10);
+Mpr121 mpr121(&i2c, Mpr121::ADD_VSS);
+Serial pc(USBTX,USBRX);
+vector<string> files;
+string file;
+int selectpos = 1;
+int oldvalue;
+int value;
+bool showingImage = false;
+bool displayImage = false;
+
+
+string toLower(string in)
+{
+ for(int i = 0; i < in.length(); i++)
+ {
+ in[i] = tolower(in[i]);
+ }
+ return in;
+}
+
+void changepos(int val2,int val1){ //compares the current position with the old one andchanges currsor accordingly.
+//val1 is the lower value ond val2 th higher possibla value
+
+if (!showingImage) {
+ if (oldvalue==val1) {
+ if (selectpos != 1)
+ selectpos--;
+ // if (selectpos < 1)selectpos = files.size(); // no more raparround
+ } else if(oldvalue==val2){
+ if (selectpos != files.size())
+ selectpos++;
+ //if (selectpos > files.size()) selectpos = 1; // no more raparound
+ }
+ }
+}
+
+void fallInterrupt() {
+ value=mpr121.read(0x00);
+ value +=mpr121.read(0x01)<<8;
+ //pc.printf("%d\r\n",value);
+ switch (value) {
+ case 0: //no button is pressed (good only to execute actions on release)
+ switch (oldvalue) { //if not do action according to button realeased.
+ case (1<<4):
+ if (showingImage) {
+ lcd.background(0xFFFFFF);
+ lcd.foreground(0xFFFFFF);
+ lcd.cls();
+ showingImage = false;
+ }
+ break;
+
+ case (1<<5):
+ if (!showingImage) {
+ displayImage = true;
+ showingImage = true;
+ }
+ break;
+
+ }
+ case 1:
+ changepos(-1,3); //cannot have a lower value as 0 i no button
+ break;
+ case 3:
+ changepos(1,2);
+ break;
+ case 2:
+ changepos((2+1),(2+4));
+ break;
+ case (2+4):
+ changepos(2,4);
+ break;
+ case 4:
+ changepos((4+2),(4+8));
+ break;
+ case (4+8):
+ changepos(4,8);
+ break;
+ case 8:
+ changepos(4+8,-1); // cannot have a highe boundry
+ break;
+
+ default:
+
+ break;
+ };
+
+ oldvalue=value;
+}
+
+void ls(char *dir)
+{
+ DIR *dp;
+ struct dirent *dirp;
+ dp = opendir(dir);
+ while((dirp = readdir(dp)) != NULL)
+ {
+ files.push_back(string(dirp->d_name));
+ }
+}
+
+int main() {
+ interrupt.fall(&fallInterrupt);
+ interrupt.mode(PullUp);
+
+ lcd.background(0xFFFFFF);
+ lcd.foreground(0xFFFFFF);
+ lcd.cls();
+ ls("/sd");
+
+ led1 = 1;
+
+ while(1) {
+ int ypos = 1;
+ if(displayImage)
+ {
+ __disable_irq();
+ file = files[selectpos - 1];
+ string ext = file.substr(file.rfind('.')+1);
+ ext = toLower(ext);
+ if(!ext.compare("bmp"))
+ {
+ RGBApixel *Colors = new RGBApixel [2];
+ file = "/sd/" + file;
+ lcd.background(0x000000);
+ lcd.foreground(0x000000);
+ lcd.cls();
+ ReadBMPFromFile(file.c_str(), Colors, &lcd);
+ showingImage = true;
+ }
+ else if(!ext.compare("jpeg") || !ext.compare("jpg"))
+ {
+ file = "/sd/" + file;
+ lcd.background(0x000000);
+ lcd.foreground(0x000000);
+ lcd.cls();
+ ReadJPEGFromFile(file.c_str(), &lcd);
+ showingImage = true;
+ }
+ else
+ {
+ showingImage = false;
+ }
+ displayImage = false;
+ __enable_irq();
+ }
+ if(!showingImage)
+ {
+ lcd.background(0xFFFFFF);
+ lcd.locate(0,ypos);
+ for(vector<string>::iterator it=files.begin(); it < files.end(); it++)
+ {
+ if(ypos == selectpos)
+ {
+ lcd.foreground(0xFF0000);
+ }
+ else
+ {
+ lcd.foreground(0x000000);
+ }
+ lcd.printf("%s",(*it).c_str());
+ ypos++;
+ lcd.locate(0,ypos);
+ }
+ }
+ led1 = !led1;
+ wait(0.05);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld Tue Oct 11 01:24:18 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/63bcd7ba4912
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/myBMP/myBMP.cpp Tue Oct 11 01:24:18 2011 +0000
@@ -0,0 +1,456 @@
+#include "myBMP.h"
+
+int BitDepth = 1;
+int Width = 1;
+int Height = 1;
+RGBApixel *Colors;
+
+bool SafeFread( char* buffer, int size, int number, FILE* fp )
+{
+ using namespace std;
+ int ItemsRead;
+ if( feof(fp) )
+ { return false; }
+ ItemsRead = (int) fread( buffer , size , number , fp );
+ if( ItemsRead < number )
+ { return false; }
+ return true;
+}
+
+bool Read32bitRow( ebmpBYTE* Buffer, int BufferSize, int Row, NokiaLCD *lcd)
+{
+ int i;
+ char Colors[4];
+ if( Width*4 > BufferSize )
+ { return false; }
+ for( i=0 ; i < Width ; i++ )
+ {
+ memcpy( (char*) &(Colors), (char*) Buffer+4*i, 4 );
+ //Blue, Green, Red, Alpha
+ int color = 0x00000000 | (Colors[2] << 16) | (Colors[1] << 8) | (Colors[0]);
+ (*lcd).pixel((130-Width)/2+i,(130-Height)/2+Row,color);
+ }
+ return true;
+}
+
+bool Read24bitRow( ebmpBYTE* Buffer, int BufferSize, int Row, NokiaLCD *lcd)
+{
+ int i;
+ char Colors[4];
+ if( Width*3 > BufferSize )
+ { return false; }
+ for( i=0 ; i < Width ; i++ )
+ {
+ memcpy( (char*) &(Colors), (char*) Buffer+3*i, 3 );
+ //Blue, Green, Red, Alpha
+ int color = 0x00000000 | (Colors[2] << 16) | (Colors[1] << 8) | (Colors[0]);
+ (*lcd).pixel((130-Width)/2+i,(130-Height)/2+Row,color);
+ }
+ return true;
+}
+
+RGBApixel GetColor( int ColorNumber)
+{
+ RGBApixel Output;
+ Output.Red = 255;
+ Output.Green = 255;
+ Output.Blue = 255;
+ Output.Alpha = 0;
+
+ if( BitDepth != 1 && BitDepth != 4 && BitDepth != 8 )
+ {
+ return Output;
+ }
+ if( !Colors )
+ {
+ return Output;
+ }
+ Output = Colors[ColorNumber];
+ return Output;
+}
+
+bool Read8bitRow( ebmpBYTE* Buffer, int BufferSize, int Row, NokiaLCD *lcd)
+{
+ int i;
+ if( Width > BufferSize )
+ { return false; }
+ for( i=0 ; i < Width ; i++ )
+ {
+ int Index = Buffer[i];
+ //Blue, Green, Red, Alpha
+ RGBApixel colors = GetColor(Index);
+ int color = 0x00000000 | (colors.Red<< 16) | (colors.Blue << 8) | (colors.Green);
+ (*lcd).pixel((130-Width)/2+i,(130-Height)/2+Row,color);
+ }
+ return true;
+}
+
+bool Read4bitRow( ebmpBYTE* Buffer, int BufferSize, int Row, NokiaLCD *lcd)
+{
+ int Shifts[2] = {4 ,0 };
+ int Masks[2] = {240,15};
+
+ int i=0;
+ int j;
+ int k=0;
+ if( Width > 2*BufferSize )
+ { return false; }
+ while( i < Width )
+ {
+ j=0;
+ while( j < 2 && i < Width )
+ {
+ int Index = (int) ( (Buffer[k]&Masks[j]) >> Shifts[j]);
+ RGBApixel colors = GetColor(Index);
+ int color = 0x00000000 | (colors.Red<< 16) | (colors.Blue << 8) | (colors.Green);
+ (*lcd).pixel((130-Width)/2+i,(130-Height)/2+Row,color);
+ i++; j++;
+ }
+ k++;
+ }
+ return true;
+}
+bool Read1bitRow( ebmpBYTE* Buffer, int BufferSize, int Row, NokiaLCD *lcd)
+{
+ int Shifts[8] = {7 ,6 ,5 ,4 ,3,2,1,0};
+ int Masks[8] = {128,64,32,16,8,4,2,1};
+
+ int i=0;
+ int j;
+ int k=0;
+
+ if( Width > 8*BufferSize )
+ { return false; }
+ while( i < Width )
+ {
+ j=0;
+ while( j < 8 && i < Width )
+ {
+ int Index = (int) ( (Buffer[k]&Masks[j]) >> Shifts[j]);
+ RGBApixel colors = GetColor(Index);
+ int color = 0x00000000 | (colors.Red<< 16) | (colors.Blue << 8) | (colors.Green);
+ (*lcd).pixel((130-Width)/2+i,(130-Height)/2+Row,color);
+ i++; j++;
+ }
+ k++;
+ }
+ return true;
+}
+
+int TellNumberOfColors( int BitDepth )
+{
+ int output = 1 << BitDepth;
+ if( BitDepth == 32 )
+ { output = 1 << 24; }
+ return output;
+}
+
+bool ReadBMPFromFile( const char* FileName, RGBApixel *Colors, NokiaLCD *lcd)
+{
+ FILE* fp = fopen( FileName, "rb" );
+ if( fp == NULL )
+ {
+ return false;
+ }
+
+ // read the file header
+
+ BMFH bmfh;
+ bool NotCorrupted = true;
+
+ NotCorrupted &= SafeFread( (char*) &(bmfh.bfType) , sizeof(ebmpWORD), 1, fp);
+
+ bool IsBitmap = false;
+
+ if( bmfh.bfType == 19778 )
+ { IsBitmap = true; }
+
+ if( !IsBitmap )
+ {
+ fclose( fp );
+ return false;
+ }
+
+ NotCorrupted &= SafeFread( (char*) &(bmfh.bfSize) , sizeof(ebmpDWORD) , 1, fp);
+ NotCorrupted &= SafeFread( (char*) &(bmfh.bfReserved1) , sizeof(ebmpWORD) , 1, fp);
+ NotCorrupted &= SafeFread( (char*) &(bmfh.bfReserved2) , sizeof(ebmpWORD) , 1, fp);
+ NotCorrupted &= SafeFread( (char*) &(bmfh.bfOffBits) , sizeof(ebmpDWORD) , 1 , fp);
+
+ // read the info header
+
+ BMIH bmih;
+
+ NotCorrupted &= SafeFread( (char*) &(bmih.biSize) , sizeof(ebmpDWORD) , 1 , fp);
+ NotCorrupted &= SafeFread( (char*) &(bmih.biWidth) , sizeof(ebmpDWORD) , 1 , fp);
+ NotCorrupted &= SafeFread( (char*) &(bmih.biHeight) , sizeof(ebmpDWORD) , 1 , fp);
+ NotCorrupted &= SafeFread( (char*) &(bmih.biPlanes) , sizeof(ebmpWORD) , 1, fp);
+ NotCorrupted &= SafeFread( (char*) &(bmih.biBitCount) , sizeof(ebmpWORD) , 1, fp);
+
+ NotCorrupted &= SafeFread( (char*) &(bmih.biCompression) , sizeof(ebmpDWORD) , 1 , fp);
+ NotCorrupted &= SafeFread( (char*) &(bmih.biSizeImage) , sizeof(ebmpDWORD) , 1 , fp);
+ NotCorrupted &= SafeFread( (char*) &(bmih.biXPelsPerMeter) , sizeof(ebmpDWORD) , 1 , fp);
+ NotCorrupted &= SafeFread( (char*) &(bmih.biYPelsPerMeter) , sizeof(ebmpDWORD) , 1 , fp);
+ NotCorrupted &= SafeFread( (char*) &(bmih.biClrUsed) , sizeof(ebmpDWORD) , 1 , fp);
+ NotCorrupted &= SafeFread( (char*) &(bmih.biClrImportant) , sizeof(ebmpDWORD) , 1 , fp);
+
+ // a safety catch: if any of the header information didn't read properly, abort
+ // future idea: check to see if at least most is self-consistent
+
+ if( !NotCorrupted )
+ {
+ fclose(fp);
+ return false;
+ }
+
+ // if bmih.biCompression 1 or 2, then the file is RLE compressed
+
+ if( bmih.biCompression == 1 || bmih.biCompression == 2 )
+ {
+ fclose(fp);
+ return false;
+ }
+
+ // if bmih.biCompression > 3, then something strange is going on
+ // it's probably an OS2 bitmap file.
+
+ if( bmih.biCompression > 3 )
+ {
+ fclose(fp);
+ return false;
+ }
+
+ if( bmih.biCompression == 3 && bmih.biBitCount != 16 )
+ {
+ fclose(fp);
+ return false;
+ }
+
+ // set the bit depth
+
+ int TempBitDepth = (int) bmih.biBitCount;
+ if( TempBitDepth != 1 && TempBitDepth != 4
+ && TempBitDepth != 8 && TempBitDepth != 16
+ && TempBitDepth != 24 && TempBitDepth != 32 )
+ {
+ fclose(fp);
+ return false;
+ }
+ BitDepth = (int)bmih.biBitCount;
+ // set the size
+
+ if( (int) bmih.biWidth <= 0 || (int) bmih.biHeight <= 0 )
+ {
+ fclose(fp);
+ return false;
+ }
+ Width = (int) bmih.biWidth;
+ Height = (int) bmih.biHeight;
+ // some preliminaries
+
+ double dBytesPerPixel = ( (double) BitDepth ) / 8.0;
+ double dBytesPerRow = dBytesPerPixel * (Width+0.0);
+ dBytesPerRow = ceil(dBytesPerRow);
+
+ int BytePaddingPerRow = 4 - ( (int) (dBytesPerRow) )% 4;
+ if( BytePaddingPerRow == 4 )
+ { BytePaddingPerRow = 0; }
+
+ // if < 16 bits, read the palette
+
+ if( BitDepth < 16 )
+ {
+ // determine the number of colors specified in the
+ // color table
+
+ int NumberOfColorsToRead = ((int) bmfh.bfOffBits - 54 )/4;
+ if( NumberOfColorsToRead > (1 << BitDepth) )
+ { NumberOfColorsToRead = (1 << BitDepth); }
+
+ int n;
+ for( n=0; n < NumberOfColorsToRead ; n++ )
+ {
+ SafeFread( (char*) &(Colors[n]) , 4 , 1 , fp);
+ }
+ for( n=NumberOfColorsToRead ; n < TellNumberOfColors(BitDepth) ; n++ )
+ {
+ RGBApixel WHITE;
+ WHITE.Red = 255;
+ WHITE.Green = 255;
+ WHITE.Blue = 255;
+ WHITE.Alpha = 0;
+ Colors[n] = WHITE;
+ }
+ }
+
+ // skip blank data if bfOffBits so indicates
+
+ int BytesToSkip = bmfh.bfOffBits - 54;;
+ if( BitDepth < 16 )
+ { BytesToSkip -= 4*(1 << BitDepth); }
+ if( BitDepth == 16 && bmih.biCompression == 3 )
+ { BytesToSkip -= 3*4; }
+ if( BytesToSkip < 0 )
+ { BytesToSkip = 0; }
+ if( BytesToSkip > 0 && BitDepth != 16 )
+ {
+ ebmpBYTE* TempSkipBYTE;
+ TempSkipBYTE = new ebmpBYTE [BytesToSkip];
+ SafeFread( (char*) TempSkipBYTE , BytesToSkip , 1 , fp);
+ delete [] TempSkipBYTE;
+ }
+
+ // This code reads 1, 4, 8, 24, and 32-bpp files
+ // with a more-efficient buffered technique.
+
+ int i,j;
+ if( BitDepth != 16 )
+ {
+ int BufferSize = (int) ( (Width*BitDepth) / 8.0 );
+ while( 8*BufferSize < Width*BitDepth )
+ { BufferSize++; }
+ while( BufferSize % 4 )
+ { BufferSize++; }
+ ebmpBYTE* Buffer;
+ Buffer = new ebmpBYTE [BufferSize];
+ j= Height-1;
+ while( j > -1 )
+ {
+ int BytesRead = (int) fread( (char*) Buffer, 1, BufferSize, fp );
+ if( BytesRead < BufferSize )
+ {
+ j = -1;
+ }
+ else
+ {
+ bool Success = false;
+ if( BitDepth == 1 )
+ { Success = Read1bitRow( Buffer, BufferSize, j , lcd); }
+ if( BitDepth == 4 )
+ { Success = Read4bitRow( Buffer, BufferSize, j , lcd); }
+ if( BitDepth == 8 )
+ { Success = Read8bitRow( Buffer, BufferSize, j , lcd); }
+ if( BitDepth == 24 )
+ { Success = Read24bitRow( Buffer, BufferSize, j , lcd); }
+ if( BitDepth == 32 )
+ { Success = Read32bitRow( Buffer, BufferSize, j , lcd); }
+ if( !Success )
+ {
+ j = -1;
+ }
+ }
+ j--;
+ }
+ delete [] Buffer;
+ }
+
+ if( BitDepth == 16 )
+ {
+ int DataBytes = Width*2;
+ int PaddingBytes = ( 4 - DataBytes % 4 ) % 4;
+
+ // set the default mask
+
+ ebmpWORD BlueMask = 31; // bits 12-16
+ ebmpWORD GreenMask = 992; // bits 7-11
+ ebmpWORD RedMask = 31744; // bits 2-6
+
+ // read the bit fields, if necessary, to
+ // override the default 5-5-5 mask
+
+ if( bmih.biCompression != 0 )
+ {
+ // read the three bit masks
+
+ ebmpWORD TempMaskWORD;
+
+ SafeFread( (char*) &RedMask , 2 , 1 , fp );
+ SafeFread( (char*) &TempMaskWORD , 2, 1, fp );
+
+ SafeFread( (char*) &GreenMask , 2 , 1 , fp );
+ SafeFread( (char*) &TempMaskWORD , 2, 1, fp );
+
+ SafeFread( (char*) &BlueMask , 2 , 1 , fp );
+ SafeFread( (char*) &TempMaskWORD , 2, 1, fp );
+ }
+
+ // read and skip any meta data
+
+ if( BytesToSkip > 0 )
+ {
+ ebmpBYTE* TempSkipBYTE;
+ TempSkipBYTE = new ebmpBYTE [BytesToSkip];
+ SafeFread( (char*) TempSkipBYTE , BytesToSkip , 1 , fp);
+ delete [] TempSkipBYTE;
+ }
+
+ // determine the red, green and blue shifts
+
+ int GreenShift = 0;
+ ebmpWORD TempShiftWORD = GreenMask;
+ while( TempShiftWORD > 31 )
+ { TempShiftWORD = TempShiftWORD>>1; GreenShift++; }
+ int BlueShift = 0;
+ TempShiftWORD = BlueMask;
+ while( TempShiftWORD > 31 )
+ { TempShiftWORD = TempShiftWORD>>1; BlueShift++; }
+ int RedShift = 0;
+ TempShiftWORD = RedMask;
+ while( TempShiftWORD > 31 )
+ { TempShiftWORD = TempShiftWORD>>1; RedShift++; }
+
+ // read the actual pixels
+
+ for( j=Height-1 ; j >= 0 ; j-- )
+ {
+ i=0;
+ int ReadNumber = 0;
+ while( ReadNumber < DataBytes )
+ {
+ ebmpWORD TempWORD;
+ SafeFread( (char*) &TempWORD , 2 , 1 , fp );
+ ReadNumber += 2;
+
+ ebmpWORD Red = RedMask & TempWORD;
+ ebmpWORD Green = GreenMask & TempWORD;
+ ebmpWORD Blue = BlueMask & TempWORD;
+
+ ebmpBYTE BlueBYTE = (ebmpBYTE) 8*(Blue>>BlueShift);
+ ebmpBYTE GreenBYTE = (ebmpBYTE) 8*(Green>>GreenShift);
+ ebmpBYTE RedBYTE = (ebmpBYTE) 8*(Red>>RedShift);
+
+ int color = 0x00000000 | (RedBYTE << 16) | (GreenBYTE << 8) | (BlueBYTE);
+ (*lcd).pixel((130-Width)/2+i,(130-Height)/2+j,color);
+ i++;
+ }
+ ReadNumber = 0;
+ while( ReadNumber < PaddingBytes )
+ {
+ ebmpBYTE TempBYTE;
+ SafeFread( (char*) &TempBYTE , 1, 1, fp);
+ ReadNumber++;
+ }
+ }
+
+ }
+
+ fclose(fp);
+ return true;
+}
+
+
+BMIH::BMIH()
+{
+ biPlanes = 1;
+ biCompression = 0;
+ biXPelsPerMeter = DefaultXPelsPerMeter;
+ biYPelsPerMeter = DefaultYPelsPerMeter;
+ biClrUsed = 0;
+ biClrImportant = 0;
+}
+
+BMFH::BMFH()
+{
+ bfType = 19778;
+ bfReserved1 = 0;
+ bfReserved2 = 0;
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/myBMP/myBMP.h Tue Oct 11 01:24:18 2011 +0000
@@ -0,0 +1,47 @@
+// Code taken and hacked from EasyBMP library by Paul Macklin
+
+#include "NokiaLCD.h"
+#include "SDFileSystem.h"
+
+#define DefaultXPelsPerMeter 3780
+#define DefaultYPelsPerMeter 3780
+
+typedef unsigned char ebmpBYTE;
+typedef unsigned short ebmpWORD;
+typedef unsigned int ebmpDWORD;
+
+typedef struct RGBApixel {
+ ebmpBYTE Blue;
+ ebmpBYTE Green;
+ ebmpBYTE Red;
+ ebmpBYTE Alpha;
+} RGBApixel;
+
+class BMFH{
+public:
+ ebmpWORD bfType;
+ ebmpDWORD bfSize;
+ ebmpWORD bfReserved1;
+ ebmpWORD bfReserved2;
+ ebmpDWORD bfOffBits;
+
+ BMFH();
+};
+
+class BMIH{
+public:
+ ebmpDWORD biSize;
+ ebmpDWORD biWidth;
+ ebmpDWORD biHeight;
+ ebmpWORD biPlanes;
+ ebmpWORD biBitCount;
+ ebmpDWORD biCompression;
+ ebmpDWORD biSizeImage;
+ ebmpDWORD biXPelsPerMeter;
+ ebmpDWORD biYPelsPerMeter;
+ ebmpDWORD biClrUsed;
+ ebmpDWORD biClrImportant;
+
+ BMIH();
+};
+bool ReadBMPFromFile( const char* FileName , RGBApixel *Colors, NokiaLCD *lcd);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/picojpeg/jpegutil.c Tue Oct 11 01:24:18 2011 +0000
@@ -0,0 +1,107 @@
+#include "jpegutil.h"
+
+FILE *jpegfile;
+int jpeg_filesize = 0;
+int jpeg_filepos = 0;
+
+unsigned char pjpeg_need_bytes_callback(unsigned char* pBuf, unsigned char buf_size, unsigned char *pBytes_actually_read, void *pCallback_data)
+{
+ unsigned int n = min((unsigned int)(jpeg_filesize - jpeg_filepos), (unsigned int)buf_size);
+ if (n && (fread(pBuf, 1, n, jpegfile) != n))
+ return PJPG_STREAM_READ_ERROR;
+ *pBytes_actually_read = (unsigned char)(n);
+ jpeg_filepos += n;
+ return 0;
+}
+
+void ReadJPEGFromFile(const char *filename, NokiaLCD *lcd)
+{
+ pjpeg_image_info_t imageInfo;
+ jpegfile = fopen(filename,"rb");
+ fseek(jpegfile, 0, SEEK_END);
+ jpeg_filesize = ftell(jpegfile);
+ jpeg_filepos = 0;
+ fseek(jpegfile, 0, SEEK_SET);
+ int status = pjpeg_decode_init(&imageInfo, pjpeg_need_bytes_callback, NULL);
+ //const unsigned int row_pitch = imageInfo.m_width * imageInfo.m_comps;
+ int mcu_x = 0;
+ int mcu_y = 0;
+
+ for ( ; ; )
+ {
+ status = pjpeg_decode_mcu();
+
+ if (status)
+ {
+ if (status != PJPG_NO_MORE_BLOCKS)
+ {
+ //pc.printf("pjpeg_decode_mcu() failed with status %u\n", status);
+ fclose(jpegfile);
+ return;
+ }
+
+ break;
+ }
+
+ if (mcu_y >= imageInfo.m_MCUSPerCol)
+ {
+ fclose(jpegfile);
+ return;
+ }
+
+ // Copy MCU's pixel blocks into the destination bitmap.
+
+ for (int y = 0; y < imageInfo.m_MCUHeight; y += 8)
+ {
+ const int by_limit = min(8, imageInfo.m_height - (mcu_y * imageInfo.m_MCUHeight + y));
+ for (int x = 0; x < imageInfo.m_MCUWidth; x += 8)
+ {
+
+ unsigned int src_ofs = (x * 8U) + (y * 16U);
+ const unsigned char *pSrcR = imageInfo.m_pMCUBufR + src_ofs;
+ const unsigned char *pSrcG = imageInfo.m_pMCUBufG + src_ofs;
+ const unsigned char *pSrcB = imageInfo.m_pMCUBufB + src_ofs;
+
+ const int bx_limit = min(8, imageInfo.m_width - (mcu_x * imageInfo.m_MCUWidth + x));
+
+ if (imageInfo.m_scanType == PJPG_GRAYSCALE)
+ {
+ for (int by = 0; by < by_limit; by++)
+ {
+ for (int bx = 0; bx < bx_limit; bx++)
+ {
+ unsigned int color = ((*pSrcR++) << 16);
+ (*lcd).pixel(mcu_x*imageInfo.m_MCUWidth+x+bx,mcu_y*imageInfo.m_MCUHeight+y+by,color);
+ }
+ pSrcR += (8 - bx_limit);
+ }
+ }
+ else
+ {
+ for (int by = 0; by < by_limit; by++)
+ {
+ for (int bx = 0; bx < bx_limit; bx++)
+ {
+ unsigned int color = ((*pSrcR++) << 16) | ((*pSrcG++) << 8) | (*pSrcB++);
+ (*lcd).pixel((130-imageInfo.m_width)/2+mcu_x*imageInfo.m_MCUWidth+x+bx,(130-imageInfo.m_height)/2+mcu_y*imageInfo.m_MCUHeight+y+by,color);
+ }
+
+ pSrcR += (8 - bx_limit);
+ pSrcG += (8 - bx_limit);
+ pSrcB += (8 - bx_limit);
+
+ }
+ }
+ }
+ }
+
+ mcu_x++;
+ if (mcu_x == imageInfo.m_MCUSPerRow)
+ {
+ mcu_x = 0;
+ mcu_y++;
+ }
+ }
+
+ fclose(jpegfile);
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/picojpeg/jpegutil.h Tue Oct 11 01:24:18 2011 +0000
@@ -0,0 +1,6 @@
+#include "picojpeg.h"
+#include "NokiaLCD.h"
+#include <vector>
+
+unsigned char pjpeg_need_bytes_callback(unsigned char* pBuf, unsigned char buf_size, unsigned char *pBytes_actually_read, void *pCallback_data);
+void ReadJPEGFromFile(const char *filename, NokiaLCD *lcd);
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/picojpeg/picojpeg.c Tue Oct 11 01:24:18 2011 +0000
@@ -0,0 +1,1736 @@
+//------------------------------------------------------------------------------
+// picojpeg v1.0 - Public domain, Rich Geldreich <richgel99@gmail.com>
+// Last modified Nov. 27, 2010
+//------------------------------------------------------------------------------
+#include "picojpeg.h"
+//------------------------------------------------------------------------------
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef signed char int8;
+typedef signed short int16;
+//------------------------------------------------------------------------------
+// Change as needed - the PJPG_MAX_WIDTH/PJPG_MAX_HEIGHT checks are only present
+// to quickly detect bogus files.
+#define PJPG_MAX_WIDTH 16384
+#define PJPG_MAX_HEIGHT 16384
+
+#define PJPG_MAXCOMPSINSCAN 3
+//------------------------------------------------------------------------------
+typedef enum
+{
+ M_SOF0 = 0xC0,
+ M_SOF1 = 0xC1,
+ M_SOF2 = 0xC2,
+ M_SOF3 = 0xC3,
+
+ M_SOF5 = 0xC5,
+ M_SOF6 = 0xC6,
+ M_SOF7 = 0xC7,
+
+ M_JPG = 0xC8,
+ M_SOF9 = 0xC9,
+ M_SOF10 = 0xCA,
+ M_SOF11 = 0xCB,
+
+ M_SOF13 = 0xCD,
+ M_SOF14 = 0xCE,
+ M_SOF15 = 0xCF,
+
+ M_DHT = 0xC4,
+
+ M_DAC = 0xCC,
+
+ M_RST0 = 0xD0,
+ M_RST1 = 0xD1,
+ M_RST2 = 0xD2,
+ M_RST3 = 0xD3,
+ M_RST4 = 0xD4,
+ M_RST5 = 0xD5,
+ M_RST6 = 0xD6,
+ M_RST7 = 0xD7,
+
+ M_SOI = 0xD8,
+ M_EOI = 0xD9,
+ M_SOS = 0xDA,
+ M_DQT = 0xDB,
+ M_DNL = 0xDC,
+ M_DRI = 0xDD,
+ M_DHP = 0xDE,
+ M_EXP = 0xDF,
+
+ M_APP0 = 0xE0,
+ M_APP15 = 0xEF,
+
+ M_JPG0 = 0xF0,
+ M_JPG13 = 0xFD,
+ M_COM = 0xFE,
+
+ M_TEM = 0x01,
+
+ M_ERROR = 0x100
+} JPEG_MARKER;
+
+#define RST0 0xD0
+//------------------------------------------------------------------------------
+const int8 ZAG[] =
+{
+ 0, 1, 8, 16, 9, 2, 3, 10,
+ 17, 24, 32, 25, 18, 11, 4, 5,
+ 12, 19, 26, 33, 40, 48, 41, 34,
+ 27, 20, 13, 6, 7, 14, 21, 28,
+ 35, 42, 49, 56, 57, 50, 43, 36,
+ 29, 22, 15, 23, 30, 37, 44, 51,
+ 58, 59, 52, 45, 38, 31, 39, 46,
+ 53, 60, 61, 54, 47, 55, 62, 63,
+};
+//------------------------------------------------------------------------------
+// 128 bytes
+static int16 gCoeffBuf[8*8];
+
+// 8*8*4 bytes * 3 = 768
+static uint8 gMCUBufR[256];
+static uint8 gMCUBufG[256];
+static uint8 gMCUBufB[256];
+
+// 256 bytes
+static int16 gQuant0[8*8];
+static int16 gQuant1[8*8];
+
+// 6 bytes
+static int16 gLastDC[3];
+
+typedef struct HuffTableT
+{
+ uint16 mMinCode[16];
+ uint16 mMaxCode[16];
+ uint8 mValPtr[16];
+} HuffTable;
+
+// DC - 192
+static HuffTable gHuffTab0;
+
+static uint8 gHuffVal0[16];
+
+static HuffTable gHuffTab1;
+static uint8 gHuffVal1[16];
+
+// AC - 672
+static HuffTable gHuffTab2;
+static uint8 gHuffVal2[256];
+
+static HuffTable gHuffTab3;
+static uint8 gHuffVal3[256];
+
+static uint8 gValidHuffTables;
+static uint8 gValidQuantTables;
+
+static uint8 gTemFlag;
+#define MAX_IN_BUF_SIZE 256
+static uint8 gInBuf[MAX_IN_BUF_SIZE];
+static uint8 gInBufOfs;
+static uint8 gInBufLeft;
+
+static uint16 gBitBuf;
+static uint8 gBitsLeft;
+//------------------------------------------------------------------------------
+static uint16 gImageXSize;
+static uint16 gImageYSize;
+static uint8 gCompsInFrame;
+static uint8 gCompIdent[3];
+static uint8 gCompHSamp[3];
+static uint8 gCompVSamp[3];
+static uint8 gCompQuant[3];
+
+static uint16 gRestartInterval;
+static uint16 gNextRestartNum;
+static uint16 gRestartsLeft;
+
+static uint8 gCompsInScan;
+static uint8 gCompList[3];
+static uint8 gCompDCTab[3]; // 0,1
+static uint8 gCompACTab[3]; // 0,1
+
+static pjpeg_scan_type_t gScanType;
+
+static uint8 gMaxBlocksPerMCU;
+static uint8 gMaxMCUXSize;
+static uint8 gMaxMCUYSize;
+static uint16 gMaxMCUSPerRow;
+static uint16 gMaxMCUSPerCol;
+static uint16 gNumMCUSRemaining;
+static uint8 gMCUOrg[6];
+
+static pjpeg_need_bytes_callback_t g_pNeedBytesCallback;
+static void *g_pCallback_data;
+//------------------------------------------------------------------------------
+static uint8 fillInBuf(void)
+{
+ unsigned char status;
+
+ // Reserve a few bytes at the beginning of the buffer for putting back ("stuffing") chars.
+ gInBufOfs = 4;
+ gInBufLeft = 0;
+
+ status = (*g_pNeedBytesCallback)(gInBuf + gInBufOfs, MAX_IN_BUF_SIZE - gInBufOfs, &gInBufLeft, g_pCallback_data);
+ if (status)
+ return status;
+
+ return 0;
+}
+//------------------------------------------------------------------------------
+static uint8 getChar(void)
+{
+ if (!gInBufLeft)
+ {
+ fillInBuf();
+ if (!gInBufLeft)
+ {
+ gTemFlag = ~gTemFlag;
+ return gTemFlag ? 0xFF : 0xD9;
+ }
+ }
+
+ gInBufLeft--;
+ return gInBuf[gInBufOfs++];
+}
+//------------------------------------------------------------------------------
+static void stuffChar(uint8 i)
+{
+ gInBufOfs--;
+ gInBuf[gInBufOfs] = i;
+ gInBufLeft++;
+}
+//------------------------------------------------------------------------------
+static uint8 getOctet(uint8 FFCheck)
+{
+ uint8 c = getChar();
+
+ if ((FFCheck) && (c == 0xFF))
+ {
+ uint8 n = getChar();
+
+ if (n)
+ {
+ stuffChar(n);
+ stuffChar(0xFF);
+ }
+ }
+
+ return c;
+}
+//------------------------------------------------------------------------------
+static uint16 getBits(uint8 numBits, uint8 FFCheck)
+{
+ uint8 origBits = numBits;
+ uint16 ret = gBitBuf;
+
+ if (numBits > 8)
+ {
+ numBits -= 8;
+
+ gBitBuf <<= gBitsLeft;
+
+ gBitBuf |= getOctet(FFCheck);
+
+ gBitBuf <<= (8 - gBitsLeft);
+
+ ret = (ret & 0xFF00) | (gBitBuf >> 8);
+ }
+
+ if (gBitsLeft < numBits)
+ {
+ gBitBuf <<= gBitsLeft;
+
+ gBitBuf |= getOctet(FFCheck);
+
+ gBitBuf <<= (numBits - gBitsLeft);
+
+ gBitsLeft = 8 - (numBits - gBitsLeft);
+ }
+ else
+ {
+ gBitsLeft = (uint8)(gBitsLeft - numBits);
+ gBitBuf <<= numBits;
+ }
+
+ return ret >> (16 - origBits);
+}
+//------------------------------------------------------------------------------
+static uint16 getBits1(uint8 numBits)
+{
+ return getBits(numBits, 0);
+}
+//------------------------------------------------------------------------------
+static uint16 getBits2(uint8 numBits)
+{
+ return getBits(numBits, 1);
+}
+//------------------------------------------------------------------------------
+static uint8 getBit(void)
+{
+ uint8 ret = 0;
+ if (gBitBuf & 0x8000)
+ ret = 1;
+
+ if (!gBitsLeft)
+ {
+ gBitBuf |= getOctet(1);
+
+ gBitsLeft += 8;
+ }
+
+ gBitsLeft--;
+ gBitBuf <<= 1;
+
+ return ret;
+}
+//------------------------------------------------------------------------------
+static uint16 getExtendTest(uint8 i)
+{
+ switch (i)
+ {
+ case 0: return 0;
+ case 1: return 0x0001;
+ case 2: return 0x0002;
+ case 3: return 0x0004;
+ case 4: return 0x0008;
+ case 5: return 0x0010;
+ case 6: return 0x0020;
+ case 7: return 0x0040;
+ case 8: return 0x0080;
+ case 9: return 0x0100;
+ case 10: return 0x0200;
+ case 11: return 0x0400;
+ case 12: return 0x0800;
+ case 13: return 0x1000;
+ case 14: return 0x2000;
+ case 15: return 0x4000;
+ default: return 0;
+ }
+}
+//------------------------------------------------------------------------------
+static int16 getExtendOffset(uint8 i)
+{
+ switch (i)
+ {
+ case 0: return 0;
+ case 1: return ((-1)<<1) + 1;
+ case 2: return ((-1)<<2) + 1;
+ case 3: return ((-1)<<3) + 1;
+ case 4: return ((-1)<<4) + 1;
+ case 5: return ((-1)<<5) + 1;
+ case 6: return ((-1)<<6) + 1;
+ case 7: return ((-1)<<7) + 1;
+ case 8: return ((-1)<<8) + 1;
+ case 9: return ((-1)<<9) + 1;
+ case 10: return ((-1)<<10) + 1;
+ case 11: return ((-1)<<11) + 1;
+ case 12: return ((-1)<<12) + 1;
+ case 13: return ((-1)<<13) + 1;
+ case 14: return ((-1)<<14) + 1;
+ case 15: return ((-1)<<15) + 1;
+ default: return 0;
+ }
+};
+//------------------------------------------------------------------------------
+static int16 huffExtend(uint16 x, uint8 s)
+{
+ return ((x < getExtendTest(s)) ? ((int16)x + getExtendOffset(s)) : (int16)x);
+}
+//------------------------------------------------------------------------------
+static uint8 huffDecode(const HuffTable* pHuffTable, const uint8* pHuffVal)
+{
+ uint8 i = 0;
+ uint8 j;
+ uint16 code = getBit();
+
+ for ( ; ; )
+ {
+ uint16 maxCode;
+
+ if (i == 16)
+ return 0;
+
+ maxCode = pHuffTable->mMaxCode[i];
+ if ((code <= maxCode) && (maxCode != 0xFFFF))
+ break;
+
+ i++;
+ code <<= 1;
+ code |= getBit();
+ }
+
+ j = pHuffTable->mValPtr[i];
+ j = (uint8)(j + (code - pHuffTable->mMinCode[i]));
+
+ return pHuffVal[j];
+}
+//------------------------------------------------------------------------------
+static void huffCreate(const uint8* pBits, HuffTable* pHuffTable)
+{
+ uint8 i = 0;
+ uint8 j = 0;
+
+ uint16 code = 0;
+
+ for ( ; ; )
+ {
+ uint8 num = pBits[i];
+
+ if (!num)
+ {
+ pHuffTable->mMinCode[i] = 0x0000;
+ pHuffTable->mMaxCode[i] = 0xFFFF;
+ pHuffTable->mValPtr[i] = 0;
+ }
+ else
+ {
+ pHuffTable->mMinCode[i] = code;
+ pHuffTable->mMaxCode[i] = code + num - 1;
+ pHuffTable->mValPtr[i] = j;
+
+ j = (uint8)(j + num);
+
+ code = (uint16)(code + num);
+ }
+
+ code <<= 1;
+
+ i++;
+ if (i > 15)
+ break;
+ }
+}
+//------------------------------------------------------------------------------
+static HuffTable* getHuffTable(uint8 index)
+{
+ // 0-1 = DC
+ // 2-3 = AC
+ switch (index)
+ {
+ case 0: return &gHuffTab0;
+ case 1: return &gHuffTab1;
+ case 2: return &gHuffTab2;
+ case 3: return &gHuffTab3;
+ default: return 0;
+ }
+}
+//------------------------------------------------------------------------------
+static uint8* getHuffVal(uint8 index)
+{
+ // 0-1 = DC
+ // 2-3 = AC
+ switch (index)
+ {
+ case 0: return gHuffVal0;
+ case 1: return gHuffVal1;
+ case 2: return gHuffVal2;
+ case 3: return gHuffVal3;
+ default: return 0;
+ }
+}
+//------------------------------------------------------------------------------
+static uint16 getMaxHuffCodes(uint8 index)
+{
+ return (index < 2) ? 12 : 255;
+}
+//------------------------------------------------------------------------------
+static uint8 readDHTMarker(void)
+{
+ uint8 bits[16];
+ uint16 left = getBits1(16);
+
+ if (left < 2)
+ return PJPG_BAD_DHT_MARKER;
+
+ left -= 2;
+
+ while (left)
+ {
+ uint8 i, tableIndex, index;
+ uint8* pHuffVal;
+ HuffTable* pHuffTable;
+ uint16 count, totalRead;
+
+ index = (uint8)getBits1(8);
+
+ if ( ((index & 0xF) > 1) || ((index & 0xF0) > 0x10) )
+ return PJPG_BAD_DHT_INDEX;
+
+ tableIndex = ((index >> 3) & 2) + (index & 1);
+
+ pHuffTable = getHuffTable(tableIndex);
+ pHuffVal = getHuffVal(tableIndex);
+
+ gValidHuffTables |= (1 << tableIndex);
+
+ count = 0;
+ for (i = 0; i <= 15; i++)
+ {
+ uint8 n = (uint8)getBits1(8);
+ bits[i] = n;
+ count = (uint16)(count + n);
+ }
+
+ if (count > getMaxHuffCodes(tableIndex))
+ return PJPG_BAD_DHT_COUNTS;
+
+ for (i = 0; i < count; i++)
+ pHuffVal[i] = (uint8)getBits1(8);
+
+ totalRead = 1 + 16 + count;
+
+ if (left < totalRead)
+ return PJPG_BAD_DHT_MARKER;
+
+ left = (uint16)(left - totalRead);
+
+ huffCreate(bits, pHuffTable);
+ }
+
+ return 0;
+}
+//------------------------------------------------------------------------------
+static void createWinogradQuant(int16* pQuant);
+
+static uint8 readDQTMarker(void)
+{
+ uint16 left = getBits1(16);
+
+ if (left < 2)
+ return PJPG_BAD_DQT_MARKER;
+
+ left -= 2;
+
+ while (left)
+ {
+ uint8 i;
+ uint8 n = (uint8)getBits1(8);
+ uint8 prec = n >> 4;
+ uint16 totalRead;
+
+ n &= 0x0F;
+
+ if (n > 1)
+ return PJPG_BAD_DQT_TABLE;
+
+ gValidQuantTables |= (n ? 2 : 1);
+
+ // read quantization entries, in zag order
+ for (i = 0; i < 64; i++)
+ {
+ uint16 temp = getBits1(8);
+
+ if (prec)
+ temp = (temp << 8) + getBits1(8);
+
+ if (n)
+ gQuant1[i] = (int16)temp;
+ else
+ gQuant0[i] = (int16)temp;
+ }
+
+ createWinogradQuant(n ? gQuant1 : gQuant0);
+
+ totalRead = 64 + 1;
+
+ if (prec)
+ totalRead += 64;
+
+ if (left < totalRead)
+ return PJPG_BAD_DQT_LENGTH;
+
+ left = (uint16)(left - totalRead);
+ }
+
+ return 0;
+}
+//------------------------------------------------------------------------------
+static uint8 readSOFMarker(void)
+{
+ uint8 i;
+ uint16 left = getBits1(16);
+
+ if (getBits1(8) != 8)
+ return PJPG_BAD_PRECISION;
+
+ gImageYSize = getBits1(16);
+
+ if ((!gImageYSize) || (gImageYSize > PJPG_MAX_HEIGHT))
+ return PJPG_BAD_HEIGHT;
+
+ gImageXSize = getBits1(16);
+
+ if ((!gImageXSize) || (gImageXSize > PJPG_MAX_WIDTH))
+ return PJPG_BAD_WIDTH;
+
+ gCompsInFrame = (uint8)getBits1(8);
+
+ if (gCompsInFrame > 3)
+ return PJPG_TOO_MANY_COMPONENTS;
+
+ if (left != (gCompsInFrame + gCompsInFrame + gCompsInFrame + 8))
+ return PJPG_BAD_SOF_LENGTH;
+
+ for (i = 0; i < gCompsInFrame; i++)
+ {
+ gCompIdent[i] = (uint8)getBits1(8);
+ gCompHSamp[i] = (uint8)getBits1(4);
+ gCompVSamp[i] = (uint8)getBits1(4);
+ gCompQuant[i] = (uint8)getBits1(8);
+
+ if (gCompQuant[i] > 1)
+ return PJPG_UNSUPPORTED_QUANT_TABLE;
+ }
+
+ return 0;
+}
+//------------------------------------------------------------------------------
+// Used to skip unrecognized markers.
+static uint8 skipVariableMarker(void)
+{
+ uint16 left = getBits1(16);
+
+ if (left < 2)
+ return PJPG_BAD_VARIABLE_MARKER;
+
+ left -= 2;
+
+ while (left)
+ {
+ getBits1(8);
+ left--;
+ }
+
+ return 0;
+}
+//------------------------------------------------------------------------------
+// Read a define restart interval (DRI) marker.
+static uint8 readDRIMarker(void)
+{
+ if (getBits1(16) != 4)
+ return PJPG_BAD_DRI_LENGTH;
+
+ gRestartInterval = getBits1(16);
+
+ return 0;
+}
+//------------------------------------------------------------------------------
+// Read a start of scan (SOS) marker.
+static uint8 readSOSMarker(void)
+{
+ uint8 i;
+ uint16 left = getBits1(16);
+ uint8 spectral_start, spectral_end, successive_high, successive_low;
+
+ gCompsInScan = (uint8)getBits1(8);
+
+ left -= 3;
+
+ if ( (left != (gCompsInScan + gCompsInScan + 3)) || (gCompsInScan < 1) || (gCompsInScan > PJPG_MAXCOMPSINSCAN) )
+ return PJPG_BAD_SOS_LENGTH;
+
+ for (i = 0; i < gCompsInScan; i++)
+ {
+ uint8 cc = (uint8)getBits1(8);
+ uint8 c = (uint8)getBits1(8);
+ uint8 ci;
+
+ left -= 2;
+
+ for (ci = 0; ci < gCompsInFrame; ci++)
+ if (cc == gCompIdent[ci])
+ break;
+
+ if (ci >= gCompsInFrame)
+ return PJPG_BAD_SOS_COMP_ID;
+
+ gCompList[i] = ci;
+ gCompDCTab[ci] = (c >> 4) & 15;
+ gCompACTab[ci] = (c & 15);
+ }
+
+ spectral_start = (uint8)getBits1(8);
+ spectral_end = (uint8)getBits1(8);
+ successive_high = (uint8)getBits1(4);
+ successive_low = (uint8)getBits1(4);
+
+ left -= 3;
+
+ while (left)
+ {
+ getBits1(8);
+ left--;
+ }
+
+ return 0;
+}
+//------------------------------------------------------------------------------
+static uint8 nextMarker(void)
+{
+ uint8 c;
+ uint8 bytes = 0;
+
+ do
+ {
+ do
+ {
+ bytes++;
+
+ c = (uint8)getBits1(8);
+
+ } while (c != 0xFF);
+
+ do
+ {
+ c = (uint8)getBits1(8);
+
+ } while (c == 0xFF);
+
+ } while (c == 0);
+
+ // If bytes > 0 here, there where extra bytes before the marker (not good).
+
+ return c;
+}
+//------------------------------------------------------------------------------
+// Process markers. Returns when an SOFx, SOI, EOI, or SOS marker is
+// encountered.
+static uint8 processMarkers(uint8* pMarker)
+{
+ for ( ; ; )
+ {
+ uint8 c = nextMarker();
+
+ switch (c)
+ {
+ case M_SOF0:
+ case M_SOF1:
+ case M_SOF2:
+ case M_SOF3:
+ case M_SOF5:
+ case M_SOF6:
+ case M_SOF7:
+ // case M_JPG:
+ case M_SOF9:
+ case M_SOF10:
+ case M_SOF11:
+ case M_SOF13:
+ case M_SOF14:
+ case M_SOF15:
+ case M_SOI:
+ case M_EOI:
+ case M_SOS:
+ {
+ *pMarker = c;
+ return 0;
+ }
+ case M_DHT:
+ {
+ readDHTMarker();
+ break;
+ }
+ // Sorry, no arithmitic support at this time. Dumb patents!
+ case M_DAC:
+ {
+ return PJPG_NO_ARITHMITIC_SUPPORT;
+ }
+ case M_DQT:
+ {
+ readDQTMarker();
+ break;
+ }
+ case M_DRI:
+ {
+ readDRIMarker();
+ break;
+ }
+ //case M_APP0: /* no need to read the JFIF marker */
+
+ case M_JPG:
+ case M_RST0: /* no parameters */
+ case M_RST1:
+ case M_RST2:
+ case M_RST3:
+ case M_RST4:
+ case M_RST5:
+ case M_RST6:
+ case M_RST7:
+ case M_TEM:
+ {
+ return PJPG_UNEXPECTED_MARKER;
+ }
+ default: /* must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn or APP0 */
+ {
+ skipVariableMarker();
+ break;
+ }
+ }
+ }
+// return 0;
+}
+//------------------------------------------------------------------------------
+// Finds the start of image (SOI) marker.
+static uint8 locateSOIMarker(void)
+{
+ uint16 bytesleft;
+
+ uint8 lastchar = (uint8)getBits1(8);
+
+ uint8 thischar = (uint8)getBits1(8);
+
+ /* ok if it's a normal JPEG file without a special header */
+
+ if ((lastchar == 0xFF) && (thischar == M_SOI))
+ return 0;
+
+ bytesleft = 4096; //512;
+
+ for ( ; ; )
+ {
+ if (--bytesleft == 0)
+ return PJPG_NOT_JPEG;
+
+ lastchar = thischar;
+
+ thischar = (uint8)getBits1(8);
+
+ if (lastchar == 0xFF)
+ {
+ if (thischar == M_SOI)
+ break;
+ else if (thischar == M_EOI) //getBits1 will keep returning M_EOI if we read past the end
+ return PJPG_NOT_JPEG;
+ }
+ }
+
+ /* Check the next character after marker: if it's not 0xFF, it can't
+ be the start of the next marker, so the file is bad */
+
+ thischar = (uint8)((gBitBuf >> 8) & 0xFF);
+
+ if (thischar != 0xFF)
+ return PJPG_NOT_JPEG;
+
+ return 0;
+}
+//------------------------------------------------------------------------------
+// Find a start of frame (SOF) marker.
+static uint8 locateSOFMarker(void)
+{
+ uint8 c;
+
+ uint8 status = locateSOIMarker();
+ if (status)
+ return status;
+
+ status = processMarkers(&c);
+ if (status)
+ return status;
+
+ switch (c)
+ {
+ case M_SOF2:
+ {
+ return PJPG_UNSUPPORTED_MODE;
+ }
+ case M_SOF0: /* baseline DCT */
+ {
+ status = readSOFMarker();
+ if (status)
+ return status;
+
+ break;
+ }
+ case M_SOF9:
+ {
+ return PJPG_NO_ARITHMITIC_SUPPORT;
+ }
+ case M_SOF1: /* extended sequential DCT */
+ default:
+ {
+ return PJPG_UNSUPPORTED_MARKER;
+ }
+ }
+
+ return 0;
+}
+//------------------------------------------------------------------------------
+// Find a start of scan (SOS) marker.
+static uint8 locateSOSMarker(uint8* pFoundEOI)
+{
+ uint8 c;
+ uint8 status;
+
+ *pFoundEOI = 0;
+
+ status = processMarkers(&c);
+ if (status)
+ return status;
+
+ if (c == M_EOI)
+ {
+ *pFoundEOI = 1;
+ return 0;
+ }
+ else if (c != M_SOS)
+ return PJPG_UNEXPECTED_MARKER;
+
+ return readSOSMarker();
+}
+//------------------------------------------------------------------------------
+static uint8 init(void)
+{
+ gImageXSize = 0;
+ gImageYSize = 0;
+ gCompsInFrame = 0;
+ gRestartInterval = 0;
+ gCompsInScan = 0;
+ gValidHuffTables = 0;
+ gValidQuantTables = 0;
+ gTemFlag = 0;
+ gInBufOfs = 0;
+ gInBufLeft = 0;
+ gBitBuf = 0;
+ gBitsLeft = 8;
+
+ getBits1(8);
+ getBits1(8);
+
+ return 0;
+}
+//------------------------------------------------------------------------------
+// This method throws back into the stream any bytes that where read
+// into the bit buffer during initial marker scanning.
+static void fixInBuffer(void)
+{
+ /* In case any 0xFF's where pulled into the buffer during marker scanning */
+
+ if (gBitsLeft > 0)
+ stuffChar((uint8)gBitBuf);
+
+ stuffChar((uint8)(gBitBuf >> 8));
+
+ gBitsLeft = 8;
+ getBits2(8);
+ getBits2(8);
+}
+//------------------------------------------------------------------------------
+// Restart interval processing.
+static uint8 processRestart(void)
+{
+ // Let's scan a little bit to find the marker, but not _too_ far.
+ // 1536 is a "fudge factor" that determines how much to scan.
+ uint16 i;
+ uint8 c = 0;
+
+ for (i = 1536; i > 0; i--)
+ if (getChar() == 0xFF)
+ break;
+
+ if (i == 0)
+ return PJPG_BAD_RESTART_MARKER;
+
+ for ( ; i > 0; i--)
+ if ((c = getChar()) != 0xFF)
+ break;
+
+ if (i == 0)
+ return PJPG_BAD_RESTART_MARKER;
+
+ // Is it the expected marker? If not, something bad happened.
+ if (c != (gNextRestartNum + M_RST0))
+ return PJPG_BAD_RESTART_MARKER;
+
+ // Reset each component's DC prediction values.
+ gLastDC[0] = 0;
+ gLastDC[1] = 0;
+ gLastDC[2] = 0;
+
+ gRestartsLeft = gRestartInterval;
+
+ gNextRestartNum = (gNextRestartNum + 1) & 7;
+
+ // Get the bit buffer going again...
+
+ gBitsLeft = 8;
+ getBits2(8);
+ getBits2(8);
+
+ return 0;
+}
+//------------------------------------------------------------------------------
+static uint8 findEOI(void)
+{
+ uint8 c;
+ uint8 status;
+
+ // Prime the bit buffer
+ gBitsLeft = 8;
+ getBits1(8);
+ getBits1(8);
+
+ // The next marker _should_ be EOI
+ status = processMarkers(&c);
+ if (status)
+ return status;
+
+ //gTotalBytesRead -= in_buf_left;
+ if (c != M_EOI)
+ return PJPG_UNEXPECTED_MARKER;
+
+ return 0;
+}
+//------------------------------------------------------------------------------
+static uint8 checkHuffTables(void)
+{
+ uint8 i;
+
+ for (i = 0; i < gCompsInScan; i++)
+ {
+ uint8 compDCTab = gCompDCTab[gCompList[i]];
+ uint8 compACTab = gCompACTab[gCompList[i]] + 2;
+
+ if ( ((gValidHuffTables & (1 << compDCTab)) == 0) ||
+ ((gValidHuffTables & (1 << compACTab)) == 0) )
+ return PJPG_UNDEFINED_HUFF_TABLE;
+ }
+
+ return 0;
+}
+//------------------------------------------------------------------------------
+static uint8 checkQuantTables(void)
+{
+ uint8 i;
+
+ for (i = 0; i < gCompsInScan; i++)
+ {
+ uint8 compQuantMask = gCompQuant[gCompList[i]] ? 2 : 1;
+
+ if ((gValidQuantTables & compQuantMask) == 0)
+ return PJPG_UNDEFINED_QUANT_TABLE;
+ }
+
+ return 0;
+}
+//------------------------------------------------------------------------------
+static uint8 initScan(void)
+{
+ uint8 foundEOI;
+ uint8 status = locateSOSMarker(&foundEOI);
+ if (status)
+ return status;
+ if (foundEOI)
+ return PJPG_UNEXPECTED_MARKER;
+
+ status = checkHuffTables();
+ if (status)
+ return status;
+
+ status = checkQuantTables();
+ if (status)
+ return status;
+
+ gLastDC[0] = 0;
+ gLastDC[1] = 0;
+ gLastDC[2] = 0;
+
+ if (gRestartInterval)
+ {
+ gRestartsLeft = gRestartInterval;
+ gNextRestartNum = 0;
+ }
+
+ fixInBuffer();
+
+ return 0;
+}
+//------------------------------------------------------------------------------
+static uint8 initFrame(void)
+{
+ if (gCompsInFrame == 1)
+ {
+ if ((gCompHSamp[0] != 1) || (gCompVSamp[0] != 1))
+ return PJPG_UNSUPPORTED_SAMP_FACTORS;
+
+ gScanType = PJPG_GRAYSCALE;
+
+ gMaxBlocksPerMCU = 1;
+ gMCUOrg[0] = 0;
+
+ gMaxMCUXSize = 8;
+ gMaxMCUYSize = 8;
+ }
+ else if (gCompsInFrame == 3)
+ {
+ if ( ((gCompHSamp[1] != 1) || (gCompVSamp[1] != 1)) ||
+ ((gCompHSamp[2] != 1) || (gCompVSamp[2] != 1)) )
+ return PJPG_UNSUPPORTED_SAMP_FACTORS;
+
+ if ((gCompHSamp[0] == 1) && (gCompVSamp[0] == 1))
+ {
+ gScanType = PJPG_YH1V1;
+
+ gMaxBlocksPerMCU = 3;
+ gMCUOrg[0] = 0;
+ gMCUOrg[1] = 1;
+ gMCUOrg[2] = 2;
+
+ gMaxMCUXSize = 8;
+ gMaxMCUYSize = 8;
+ }
+ else if ((gCompHSamp[0] == 2) && (gCompVSamp[0] == 2))
+ {
+ gScanType = PJPG_YH2V2;
+
+ gMaxBlocksPerMCU = 6;
+ gMCUOrg[0] = 0;
+ gMCUOrg[1] = 0;
+ gMCUOrg[2] = 0;
+ gMCUOrg[3] = 0;
+ gMCUOrg[4] = 1;
+ gMCUOrg[5] = 2;
+
+ gMaxMCUXSize = 16;
+ gMaxMCUYSize = 16;
+ }
+ else
+ return PJPG_UNSUPPORTED_SAMP_FACTORS;
+ }
+ else
+ return PJPG_UNSUPPORTED_COLORSPACE;
+
+ gMaxMCUSPerRow = (gImageXSize + (gMaxMCUXSize - 1)) >> ((gMaxMCUXSize == 8) ? 3 : 4);
+ gMaxMCUSPerCol = (gImageYSize + (gMaxMCUYSize - 1)) >> ((gMaxMCUYSize == 8) ? 3 : 4);
+
+ gNumMCUSRemaining = gMaxMCUSPerRow * gMaxMCUSPerCol;
+
+ return 0;
+}
+/*----------------------------------------------------------------------------*/
+#define DCT_SCALE_BITS 7
+
+#define DCT_SCALE (1U << DCT_SCALE_BITS)
+
+#define DESCALE(x) (((x) + (1U << (DCT_SCALE_BITS - 1))) >> DCT_SCALE_BITS)
+
+#define WFIX(x) ((x) * DCT_SCALE + 0.5f)
+
+#define WINOGRAD_QUANT_SCALE_BITS 10
+
+const uint8 gWinogradQuant[] =
+{
+ 128, 178, 178, 167, 246, 167, 151, 232,
+ 232, 151, 128, 209, 219, 209, 128, 101,
+ 178, 197, 197, 178, 101, 69, 139, 167,
+ 177, 167, 139, 69, 35, 96, 131, 151,
+ 151, 131, 96, 35, 49, 91, 118, 128,
+ 118, 91, 49, 46, 81, 101, 101, 81,
+ 46, 42, 69, 79, 69, 42, 35, 54,
+ 54, 35, 28, 37, 28, 19, 19, 10,
+};
+
+static void createWinogradQuant(int16* pQuant)
+{
+ uint8 i;
+
+ for (i = 0; i < 64; i++)
+ {
+ long x = pQuant[i];
+ x *= gWinogradQuant[i];
+ pQuant[i] = (int16)((x + (1 << (WINOGRAD_QUANT_SCALE_BITS - DCT_SCALE_BITS - 1))) >> (WINOGRAD_QUANT_SCALE_BITS - DCT_SCALE_BITS));
+ }
+}
+
+// 1/cos(4*pi/16)
+// 362, 256+106
+#define b1 362
+
+// 1/cos(6*pi/16)
+// 669, 256+256+157
+#define b2 669
+
+// 1/cos(4*pi/16)
+// 362, 256+106
+#define b3 362
+
+// 1/cos(2*pi/16)
+// 277, 256+21
+#define b4 277
+
+// 1/(cos(2*pi/16) + cos(6*pi/16))
+// 196, 196
+#define b5 196
+
+static int16 imul_b1_b3(int16 w)
+{
+ long x = (w * 362L);
+ x += 128L;
+ return (int16)(x >> 8);
+}
+
+static int16 imul_b2(int16 w)
+{
+ long x = (w * 669L);
+ x += 128L;
+ return (int16)(x >> 8);
+}
+
+static int16 imul_b4(int16 w)
+{
+ long x = (w * 277L);
+ x += 128L;
+ return (int16)(x >> 8);
+}
+
+static int16 imul_b5(int16 w)
+{
+ long x = (w * 196L);
+ x += 128L;
+ return (int16)(x >> 8);
+}
+
+static uint8 clamp(int16 s)
+{
+ if ((uint16)s > 255U)
+ {
+ if (s < 0)
+ return 0;
+ else if (s > 255)
+ return 255;
+ }
+
+ return (uint8)s;
+}
+
+static void idctRows(void)
+{
+ uint8 i;
+ int16* pSrc = gCoeffBuf;
+
+ for (i = 0; i < 8; i++)
+ {
+ int16 src4 = *(pSrc+5);
+ int16 src7 = *(pSrc+3);
+ int16 x4 = src4 - src7;
+ int16 x7 = src4 + src7;
+
+ int16 src5 = *(pSrc+1);
+ int16 src6 = *(pSrc+7);
+ int16 x5 = src5 + src6;
+ int16 x6 = src5 - src6;
+
+ int16 tmp1 = imul_b5(x4 - x6);
+ int16 stg26 = imul_b4(x6) - tmp1;
+
+ int16 x24 = tmp1 - imul_b2(x4);
+
+ int16 x15 = x5 - x7;
+ int16 x17 = x5 + x7;
+
+ int16 tmp2 = stg26 - x17;
+ int16 tmp3 = imul_b1_b3(x15) - tmp2;
+ int16 x44 = tmp3 + x24;
+
+ int16 src0 = *(pSrc+0);
+ int16 src1 = *(pSrc+4);
+ int16 x30 = src0 + src1;
+ int16 x31 = src0 - src1;
+
+ int16 src2 = *(pSrc+2);
+ int16 src3 = *(pSrc+6);
+ int16 x12 = src2 - src3;
+ int16 x13 = src2 + src3;
+
+ int16 x32 = imul_b1_b3(x12) - x13;
+
+ int16 x40 = x30 + x13;
+ int16 x43 = x30 - x13;
+ int16 x41 = x31 + x32;
+ int16 x42 = x31 - x32;
+
+ *(pSrc+0) = x40 + x17;
+ *(pSrc+1) = x41 + tmp2;
+ *(pSrc+2) = x42 + tmp3;
+ *(pSrc+3) = x43 - x44;
+ *(pSrc+4) = x43 + x44;
+ *(pSrc+5) = x42 - tmp3;
+ *(pSrc+6) = x41 - tmp2;
+ *(pSrc+7) = x40 - x17;
+
+ pSrc += 8;
+ }
+}
+
+static void idctCols(void)
+{
+ uint8 i;
+
+ int16* pSrc = gCoeffBuf;
+
+ for (i = 0; i < 8; i++)
+ {
+ int16 src4 = *(pSrc+5*8);
+ int16 src7 = *(pSrc+3*8);
+ int16 x4 = src4 - src7;
+ int16 x7 = src4 + src7;
+
+ int16 src5 = *(pSrc+1*8);
+ int16 src6 = *(pSrc+7*8);
+ int16 x5 = src5 + src6;
+ int16 x6 = src5 - src6;
+
+ int16 tmp1 = imul_b5(x4 - x6);
+ int16 stg26 = imul_b4(x6) - tmp1;
+
+ int16 x24 = tmp1 - imul_b2(x4);
+
+ int16 x15 = x5 - x7;
+ int16 x17 = x5 + x7;
+
+ int16 tmp2 = stg26 - x17;
+ int16 tmp3 = imul_b1_b3(x15) - tmp2;
+ int16 x44 = tmp3 + x24;
+
+ int16 src0 = *(pSrc+0*8);
+ int16 src1 = *(pSrc+4*8);
+ int16 x30 = src0 + src1;
+ int16 x31 = src0 - src1;
+
+ int16 src2 = *(pSrc+2*8);
+ int16 src3 = *(pSrc+6*8);
+ int16 x12 = src2 - src3;
+ int16 x13 = src2 + src3;
+
+ int16 x32 = imul_b1_b3(x12) - x13;
+
+ int16 x40 = x30 + x13;
+ int16 x43 = x30 - x13;
+ int16 x41 = x31 + x32;
+ int16 x42 = x31 - x32;
+
+ *(pSrc+0*8) = clamp(DESCALE(x40 + x17) + 128);
+ *(pSrc+1*8) = clamp(DESCALE(x41 + tmp2) + 128);
+ *(pSrc+2*8) = clamp(DESCALE(x42 + tmp3) + 128);
+ *(pSrc+3*8) = clamp(DESCALE(x43 - x44) + 128);
+ *(pSrc+4*8) = clamp(DESCALE(x43 + x44) + 128);
+ *(pSrc+5*8) = clamp(DESCALE(x42 - tmp3) + 128);
+ *(pSrc+6*8) = clamp(DESCALE(x41 - tmp2) + 128);
+ *(pSrc+7*8) = clamp(DESCALE(x40 - x17) + 128);
+
+ pSrc++;
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+static uint8 addAndClamp(uint8 a, int16 b)
+{
+ b = a + b;
+
+ if ((uint16)b > 255U)
+ {
+ if (b < 0)
+ return 0;
+ else if (b > 255)
+ return 255;
+ }
+
+ return (uint8)b;
+}
+/*----------------------------------------------------------------------------*/
+static uint8 subAndClamp(uint8 a, int16 b)
+{
+ b = a - b;
+
+ if ((uint16)b > 255U)
+ {
+ if (b < 0)
+ return 0;
+ else if (b > 255)
+ return 255;
+ }
+
+ return (uint8)b;
+}
+/*----------------------------------------------------------------------------*/
+// 103/256
+//R = Y + 1.402 (Cr-128)
+
+// 88/256, 183/256
+//G = Y - 0.34414 (Cb-128) - 0.71414 (Cr-128)
+
+// 198/256
+//B = Y + 1.772 (Cb-128)
+/*----------------------------------------------------------------------------*/
+static void upsampleCb(uint8 srcOfs, uint8 dstOfs)
+{
+ // Cb - affects G and B
+ uint8 x, y;
+ int16* pSrc = gCoeffBuf + srcOfs;
+ uint8* pDstG = gMCUBufG + dstOfs;
+ uint8* pDstB = gMCUBufB + dstOfs;
+ for (y = 0; y < 4; y++)
+ {
+ for (x = 0; x < 4; x++)
+ {
+ uint8 cb = (uint8)*pSrc++;
+ int16 cbG, cbB;
+
+ cbG = ((cb * 88U) >> 8U) - 44U;
+ pDstG[0] = subAndClamp(pDstG[0], cbG);
+ pDstG[1] = subAndClamp(pDstG[1], cbG);
+ pDstG[8] = subAndClamp(pDstG[8], cbG);
+ pDstG[9] = subAndClamp(pDstG[9], cbG);
+
+ cbB = (cb + ((cb * 198U) >> 8U)) - 227U;
+ pDstB[0] = addAndClamp(pDstB[0], cbB);
+ pDstB[1] = addAndClamp(pDstB[1], cbB);
+ pDstB[8] = addAndClamp(pDstB[8], cbB);
+ pDstB[9] = addAndClamp(pDstB[9], cbB);
+
+ pDstG += 2;
+ pDstB += 2;
+ }
+
+ pSrc = pSrc - 4 + 8;
+ pDstG = pDstG - 8 + 16;
+ pDstB = pDstB - 8 + 16;
+ }
+}
+/*----------------------------------------------------------------------------*/
+// 103/256
+//R = Y + 1.402 (Cr-128)
+
+// 88/256, 183/256
+//G = Y - 0.34414 (Cb-128) - 0.71414 (Cr-128)
+
+// 198/256
+//B = Y + 1.772 (Cb-128)
+/*----------------------------------------------------------------------------*/
+static void upsampleCr(uint8 srcOfs, uint8 dstOfs)
+{
+ // Cr - affects R and G
+ uint8 x, y;
+ int16* pSrc = gCoeffBuf + srcOfs;
+ uint8* pDstR = gMCUBufR + dstOfs;
+ uint8* pDstG = gMCUBufG + dstOfs;
+ for (y = 0; y < 4; y++)
+ {
+ for (x = 0; x < 4; x++)
+ {
+ uint8 cr = (uint8)*pSrc++;
+ int16 crR, crG;
+
+ crR = (cr + ((cr * 103U) >> 8U)) - 179;
+ pDstR[0] = addAndClamp(pDstR[0], crR);
+ pDstR[1] = addAndClamp(pDstR[1], crR);
+ pDstR[8] = addAndClamp(pDstR[8], crR);
+ pDstR[9] = addAndClamp(pDstR[9], crR);
+
+ crG = ((cr * 183U) >> 8U) - 91;
+ pDstG[0] = subAndClamp(pDstG[0], crG);
+ pDstG[1] = subAndClamp(pDstG[1], crG);
+ pDstG[8] = subAndClamp(pDstG[8], crG);
+ pDstG[9] = subAndClamp(pDstG[9], crG);
+
+ pDstR += 2;
+ pDstG += 2;
+ }
+
+ pSrc = pSrc - 4 + 8;
+ pDstR = pDstR - 8 + 16;
+ pDstG = pDstG - 8 + 16;
+ }
+}
+/*----------------------------------------------------------------------------*/
+static void copyY(uint8 dstOfs)
+{
+ uint8 i;
+ uint8* pRDst = gMCUBufR + dstOfs;
+ uint8* pGDst = gMCUBufG + dstOfs;
+ uint8* pBDst = gMCUBufB + dstOfs;
+ int16* pSrc = gCoeffBuf;
+
+ for (i = 64; i > 0; i--)
+ {
+ uint8 c = (uint8)*pSrc++;
+
+ *pRDst++ = c;
+ *pGDst++ = c;
+ *pBDst++ = c;
+ }
+}
+/*----------------------------------------------------------------------------*/
+static void convertCb(uint8 dstOfs)
+{
+ uint8 i;
+ uint8* pDstG = gMCUBufG + dstOfs;
+ uint8* pDstB = gMCUBufB + dstOfs;
+ int16* pSrc = gCoeffBuf;
+
+ for (i = 64; i > 0; i--)
+ {
+ uint8 cb = (uint8)*pSrc++;
+ int16 cbG, cbB;
+
+ cbG = ((cb * 88U) >> 8U) - 44U;
+ *pDstG++ = subAndClamp(pDstG[0], cbG);
+
+ cbB = (cb + ((cb * 198U) >> 8U)) - 227U;
+ *pDstB++ = addAndClamp(pDstB[0], cbB);
+ }
+}
+/*----------------------------------------------------------------------------*/
+static void convertCr(uint8 dstOfs)
+{
+ uint8 i;
+ uint8* pDstR = gMCUBufR + dstOfs;
+ uint8* pDstG = gMCUBufG + dstOfs;
+ int16* pSrc = gCoeffBuf;
+
+ for (i = 64; i > 0; i--)
+ {
+ uint8 cr = (uint8)*pSrc++;
+ int16 crR, crG;
+
+ crR = (cr + ((cr * 103U) >> 8U)) - 179;
+ *pDstR++ = addAndClamp(pDstR[0], crR);
+
+ crG = ((cr * 183U) >> 8U) - 91;
+ *pDstG++ = subAndClamp(pDstG[0], crG);
+ }
+}
+/*----------------------------------------------------------------------------*/
+static void transformBlock(uint8 mcuBlock)
+{
+ idctRows();
+ idctCols();
+
+ switch (gScanType)
+ {
+ case PJPG_GRAYSCALE:
+ {
+ copyY(0);
+ break;
+ }
+ case PJPG_YH1V1:
+ {
+ switch (mcuBlock)
+ {
+ case 0:
+ {
+ copyY(0);
+ break;
+ }
+ case 1:
+ {
+ convertCb(0);
+ break;
+ }
+ case 2:
+ {
+ convertCr(0);
+ break;
+ }
+ }
+
+ break;
+ }
+ case PJPG_YH2V2:
+ {
+ switch (mcuBlock)
+ {
+ case 0:
+ {
+ copyY(0);
+ break;
+ }
+ case 1:
+ {
+ copyY(64);
+ break;
+ }
+ case 2:
+ {
+ copyY(128);
+ break;
+ }
+ case 3:
+ {
+ copyY(192);
+ break;
+ }
+ case 4:
+ {
+ upsampleCb(0, 0);
+ upsampleCb(4, 64);
+ upsampleCb(4*8, 128);
+ upsampleCb(4+4*8, 192);
+ break;
+ }
+ case 5:
+ {
+ upsampleCr(0, 0);
+ upsampleCr(4, 64);
+ upsampleCr(4*8, 128);
+ upsampleCr(4+4*8, 192);
+ break;
+ }
+ }
+ }
+ }
+}
+//------------------------------------------------------------------------------
+static uint8 decodeNextMCU(void)
+{
+ uint8 status;
+ uint8 mcuBlock;
+
+ if (gRestartInterval)
+ {
+ if (gRestartsLeft == 0)
+ {
+ status = processRestart();
+ if (status)
+ return status;
+ }
+ gRestartsLeft--;
+ }
+
+ for (mcuBlock = 0; mcuBlock < gMaxBlocksPerMCU; mcuBlock++)
+ {
+ uint8 componentID = gMCUOrg[mcuBlock];
+ uint8 compQuant = gCompQuant[componentID];
+ uint8 compDCTab = gCompDCTab[componentID];
+ uint8 numExtraBits, compACTab, k;
+ const int16* pQ = compQuant ? gQuant1 : gQuant0;
+ uint16 r, dc;
+
+ uint8 s = huffDecode(compDCTab ? &gHuffTab1 : &gHuffTab0, compDCTab ? gHuffVal1 : gHuffVal0);
+
+ r = 0;
+ numExtraBits = s & 0xF;
+ if (numExtraBits)
+ r = getBits2(numExtraBits);
+ dc = huffExtend(r, s);
+
+ dc = dc + gLastDC[componentID];
+ gLastDC[componentID] = dc;
+
+ gCoeffBuf[0] = dc * pQ[0];
+
+ compACTab = gCompACTab[componentID];
+
+ for (k = 1; k < 64; k++)
+ {
+ uint16 extraBits;
+
+ s = huffDecode(compACTab ? &gHuffTab3 : &gHuffTab2, compACTab ? gHuffVal3 : gHuffVal2);
+
+ extraBits = 0;
+ numExtraBits = s & 0xF;
+ if (numExtraBits)
+ extraBits = getBits2(numExtraBits);
+
+ r = s >> 4;
+ s &= 15;
+
+ if (s)
+ {
+ int16 ac;
+
+ if (r)
+ {
+ if ((k + r) > 63)
+ return PJPG_DECODE_ERROR;
+
+ while (r)
+ {
+ gCoeffBuf[ZAG[k++]] = 0;
+ r--;
+ }
+ }
+
+ ac = huffExtend(extraBits, s);
+
+ gCoeffBuf[ZAG[k]] = ac * pQ[k];
+ }
+ else
+ {
+ if (r == 15)
+ {
+ if ((k + 16) > 64)
+ return PJPG_DECODE_ERROR;
+
+ for (r = 16; r > 0; r--)
+ gCoeffBuf[ZAG[k++]] = 0;
+
+ k--; // - 1 because the loop counter is k
+ }
+ else
+ break;
+ }
+ }
+
+ while (k < 64)
+ gCoeffBuf[ZAG[k++]] = 0;
+
+ transformBlock(mcuBlock);
+ }
+
+ return 0;
+}
+//------------------------------------------------------------------------------
+unsigned char pjpeg_decode_mcu(void)
+{
+ uint8 status;
+
+ if (!gNumMCUSRemaining)
+ return PJPG_NO_MORE_BLOCKS;
+
+ status = decodeNextMCU();
+ if (status)
+ return status;
+
+ gNumMCUSRemaining--;
+
+ return 0;
+}
+//------------------------------------------------------------------------------
+unsigned char pjpeg_decode_init(pjpeg_image_info_t *pInfo, pjpeg_need_bytes_callback_t pNeed_bytes_callback, void *pCallback_data)
+{
+ uint8 status;
+
+ g_pNeedBytesCallback = pNeed_bytes_callback;
+ g_pCallback_data = pCallback_data;
+
+ status = init();
+ if (status)
+ return status;
+
+ status = locateSOFMarker();
+ if (status)
+ return status;
+
+ status = initFrame();
+ if (status)
+ return status;
+
+ status = initScan();
+ if (status)
+ return status;
+
+ pInfo->m_width = gImageXSize;
+ pInfo->m_height = gImageYSize;
+ pInfo->m_comps = gCompsInFrame;
+ pInfo->m_scanType = gScanType;
+ pInfo->m_MCUSPerRow = gMaxMCUSPerRow;
+ pInfo->m_MCUSPerCol = gMaxMCUSPerCol;
+ pInfo->m_MCUWidth = gMaxMCUXSize;
+ pInfo->m_MCUHeight = gMaxMCUYSize;
+ pInfo->m_pMCUBufR = gMCUBufR;
+ pInfo->m_pMCUBufG = gMCUBufG;
+ pInfo->m_pMCUBufB = gMCUBufB;
+
+ return 0;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/picojpeg/picojpeg.h Tue Oct 11 01:24:18 2011 +0000
@@ -0,0 +1,102 @@
+//------------------------------------------------------------------------------
+// picojpeg v1.0 - Public domain, Rich Geldreich <richgel99@gmail.com>
+//------------------------------------------------------------------------------
+#ifndef PICOJPEG_H
+#define PICOJPEG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Error codes
+enum
+{
+ PJPG_NO_MORE_BLOCKS = 1,
+ PJPG_BAD_DHT_COUNTS,
+ PJPG_BAD_DHT_INDEX,
+ PJPG_BAD_DHT_MARKER,
+ PJPG_BAD_DQT_MARKER,
+ PJPG_BAD_DQT_TABLE,
+ PJPG_BAD_PRECISION,
+ PJPG_BAD_HEIGHT,
+ PJPG_BAD_WIDTH,
+ PJPG_TOO_MANY_COMPONENTS,
+ PJPG_BAD_SOF_LENGTH,
+ PJPG_BAD_VARIABLE_MARKER,
+ PJPG_BAD_DRI_LENGTH,
+ PJPG_BAD_SOS_LENGTH,
+ PJPG_BAD_SOS_COMP_ID,
+ PJPG_W_EXTRA_BYTES_BEFORE_MARKER,
+ PJPG_NO_ARITHMITIC_SUPPORT,
+ PJPG_UNEXPECTED_MARKER,
+ PJPG_NOT_JPEG,
+ PJPG_UNSUPPORTED_MARKER,
+ PJPG_BAD_DQT_LENGTH,
+ PJPG_TOO_MANY_BLOCKS,
+ PJPG_UNDEFINED_QUANT_TABLE,
+ PJPG_UNDEFINED_HUFF_TABLE,
+ PJPG_NOT_SINGLE_SCAN,
+ PJPG_UNSUPPORTED_COLORSPACE,
+ PJPG_UNSUPPORTED_SAMP_FACTORS,
+ PJPG_DECODE_ERROR,
+ PJPG_BAD_RESTART_MARKER,
+ PJPG_ASSERTION_ERROR,
+ PJPG_BAD_SOS_SPECTRAL,
+ PJPG_BAD_SOS_SUCCESSIVE,
+ PJPG_STREAM_READ_ERROR,
+ PJPG_NOTENOUGHMEM,
+ PJPG_UNSUPPORTED_COMP_IDENT,
+ PJPG_UNSUPPORTED_QUANT_TABLE,
+ PJPG_UNSUPPORTED_MODE,
+};
+
+// Scan types - currently only GRAYSCALE, YH1V1, and YH2V2 are actually supported.
+typedef enum
+{
+ PJPG_GRAYSCALE,
+ PJPG_YH1V1,
+ PJPG_YH2V1,
+ PJPG_YH1V2,
+ PJPG_YH2V2
+} pjpeg_scan_type_t;
+
+typedef struct
+{
+ // Image resolution
+ int m_width;
+ int m_height;
+ // Number of components (1 or 3)
+ int m_comps;
+ // Total number of minimum coded units (MCU's) per row/col.
+ int m_MCUSPerRow;
+ int m_MCUSPerCol;
+ // Scan type
+ pjpeg_scan_type_t m_scanType;
+ // MCU width/height in pixels
+ int m_MCUWidth;
+ int m_MCUHeight;
+ // Pointers to internal MCU pixel component buffers.
+ // These buffers Will be filled with pixels each time pjpegDecodeMCU() is called successfully.
+ // Each MCU consists of (m_MCUWidth/8)*(m_MCUHeight/8) blocks (currently either 1 for greyscale/no subsampling, or 4 for H2V2 sampling factors), where each block is a contiguous array of 64 (8x8) bytes.
+ // For greyscale images, only the values in m_pMCUBufR are valid.
+ unsigned char *m_pMCUBufR;
+ unsigned char *m_pMCUBufG;
+ unsigned char *m_pMCUBufB;
+} pjpeg_image_info_t;
+
+typedef unsigned char (*pjpeg_need_bytes_callback_t)(unsigned char* pBuf, unsigned char buf_size, unsigned char *pBytes_actually_read, void *pCallback_data);
+
+// Initializes the decompressor. Returns 0 on success, or one of the above error codes on failure.
+// pNeed_bytes_callback will be called to fill the decompressor's internal input buffer.
+// Not thread safe.
+unsigned char pjpeg_decode_init(pjpeg_image_info_t *pInfo, pjpeg_need_bytes_callback_t pNeed_bytes_callback, void *pCallback_data);
+
+// Decompresses the file's next MCU. Returns 0 on success, PJPG_NO_MORE_BLOCKS if no more blocks are available, or an error code.
+// Must be called a total of m_MCUSPerRow*m_MCUSPerCol times to completely decompress the image.
+unsigned char pjpeg_decode_mcu(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // PICOJPEG_H