Martin Sturm
/
Lab3
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
diff -r 000000000000 -r c546b51ecf0b FATFileSystem.lib --- /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
diff -r 000000000000 -r c546b51ecf0b MPR121/mpr121.cpp --- /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
diff -r 000000000000 -r c546b51ecf0b MPR121/mpr121.h --- /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
diff -r 000000000000 -r c546b51ecf0b NokiaLCD/NokiaLCD.cpp --- /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; +}
diff -r 000000000000 -r c546b51ecf0b NokiaLCD/NokiaLCD.h --- /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 + +
diff -r 000000000000 -r c546b51ecf0b SDFileSystem/SDFileSystem.cpp --- /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; +}
diff -r 000000000000 -r c546b51ecf0b SDFileSystem/SDFileSystem.h --- /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
diff -r 000000000000 -r c546b51ecf0b main.cpp --- /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); + } +}
diff -r 000000000000 -r c546b51ecf0b mbed.bld --- /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
diff -r 000000000000 -r c546b51ecf0b myBMP/myBMP.cpp --- /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
diff -r 000000000000 -r c546b51ecf0b myBMP/myBMP.h --- /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);
diff -r 000000000000 -r c546b51ecf0b picojpeg/jpegutil.c --- /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
diff -r 000000000000 -r c546b51ecf0b picojpeg/jpegutil.h --- /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
diff -r 000000000000 -r c546b51ecf0b picojpeg/picojpeg.c --- /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; +}
diff -r 000000000000 -r c546b51ecf0b picojpeg/picojpeg.h --- /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