
Versión de Firmware con funciones de RAM incorporadas.
Dependencies: mbed
Fork of VmRecorderV1dot1 by
Revision 0:3d456b8ce449, committed 2015-06-15
- Comitter:
- JuanManuelAmador
- Date:
- Mon Jun 15 15:34:27 2015 +0000
- Child:
- 1:a3c9b672b8e2
- Commit message:
- prueba
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Doggy/doggy.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,152 @@ +#include "doggy.h" + +DogMLCD::DogMLCD( SPI& spi, PinName cs, PinName a0 ) : spi_(spi), cs_(cs), a0_(a0) +{ + //b_ = (char*)calloc( 1024, 1 ); + XFont = xfont_8; + b_ = w_; + Clear(); + const unsigned char c[] = { + 0x40, // display start line + 0-63 + 0xa1, // ADC set 0xA1 + 0 = normal (for reverse view) / +1 = reverse (for normal view) + 0xc0, // common output mode + 0 = normal / + 0xF reverse + 0xa6, // dispaly mode 0xA6 + 0 = normal / 1 = reverse + 0xa2, // set bias 0xa20 + 0 = 1/9 / +1 = 1/7 + 0x2f, // power control: 4 booster on + 2 regulator on + 1 follower on + 0xf8, 0x00, // set booster ratio , value 0=4x, 1=5x, 2=6x + 0x27, // set voltage regulator (0x20) to 7 + 0x81, 0x18, // set electronic volume , value + 0xac, 0x00, // static indicator set 0xAC +0 = off / +1 = on , 0 = flash mode + 0xaf // display 0xAE +0 = off / +1 = on + }; + + spi_.format( 8, 0 ); + spi_.frequency( 1000000 ); + cs_ = 0; + a0_ = 0; wait_us( DOGMLCD_TIME ); + for( int i = 0 ; i < sizeof( c ); i++ ) + spi_.write( c[i] ); + cs_ = 1; +} + +void DogMLCD::AttachScreen( char* screen ) +{ + b_ = screen; +} + +void DogMLCD::DetachScreen() +{ + b_ = w_; +} + +#define FASTPOKE( x, y ) b_[ ( ( y & 56 ) << 4 ) + ( x & 127 ) ] |= DOGMLCD_on[ y & 7 ]; +#define FASTWIPE( x, y ) b_[ ( ( y & 56 ) << 4 ) + ( x & 127 ) ] &= DOGMLCD_off[ y & 7 ]; +#define FASTINV( x, y ) b_[ ( ( y & 56 ) << 4 ) + ( x & 127 ) ] ^= DOGMLCD_on[ y & 7 ]; + + +void DogMLCD::Poke( int x, int y ) +{ + if( ( x & 0xFF80 ) == 0 && ( y & 0xFFC0 ) == 0 ) + FASTPOKE( x, y ) +} +void DogMLCD::Wipe( int x, int y ) +{ + if( ( x & 0xFF80 ) == 0 && ( y & 0xFFC0 ) == 0 ) + FASTWIPE( x, y ) +} +void DogMLCD::Inv( int x, int y ) +{ + if( ( x & 0xFF80 ) == 0 && ( y & 0xFFC0 ) == 0 ) + FASTINV( x, y ) +} + +void DogMLCD::InvRect( int x0, int y0, int x1, int y1 ) +{ + for(int i = y0; i < y1 + 1; i++){ + for(int j = x0; j < x1 + 1; j++){ + Inv(j,i); + } + } +} +void DogMLCD::Clear() +{ + int i = 1024; + char* p = b_; + while( i-- ) + *p++ = 0; +} +void DogMLCD::Flush() +{ + char* p = b_; + spi_.format( 8, 0 ); + spi_.frequency( DOGMLCD_MHZ ); + cs_ = 0; + for( int page = 0xB0 ; page < 0xB8 ; page++ ) + { + a0_ = 0; wait_us( DOGMLCD_TIME ); + spi_.write( page ); spi_.write( 0x10 ); spi_.write( 0x00 ); + + a0_ = 1; wait_us( DOGMLCD_TIME ); + int i = 128; + while( i-- ) + spi_.write( *p++ ); + } + cs_ = 1; +} +void DogMLCD::Flush( unsigned char page, int x0, int x1 ) +{ + page &= 7; + BOUND( x0, 0, 127 ); + BOUND( x1, 0, 127 ); + ORDER( x0 , x1 ) + char* p = b_ + ( page << 7 ) + x0; + spi_.format( 8, 0 ); + spi_.frequency( DOGMLCD_MHZ ); + cs_ = 0; + a0_ = 0; wait_us( DOGMLCD_TIME ); + spi_.write( 0xB0 + page ); spi_.write( 0x10 ); spi_.write( 0x00 ); + + a0_ = 1; wait_us( DOGMLCD_TIME ); + int i = x1 - x0 + 1; + while( i-- ) + spi_.write( *p++ ); + cs_ = 1; +} +void DogMLCD::Page( unsigned char page0, unsigned char page1 ) +{ + page0 &= 7; + if( page1 == 0 ) page1 = page0; + else + { + page1 &= 7; + ORDER( page0, page1 ); + } + char* p = b_ + ( page0 << 7 ); + spi_.format( 8, 0 ); + spi_.frequency( DOGMLCD_MHZ ); + cs_ = 0; + for( int page = 0xB0 + page0 ; page <= ( 0xB0 + page1 ) ; page++ ) + { + a0_ = 0; wait_us( DOGMLCD_TIME ); + spi_.write( page ); spi_.write( 0x10 ); spi_.write( 0x00 ); + + a0_ = 1; wait_us( DOGMLCD_TIME ); + int i = 128; + while( i-- ) + spi_.write( *p++ ); + } + cs_ = 1; +} +void DogMLCD::Paste( char* screen, doggy_op op ) +{ + int i = 1024; + char* p = b_; + char* q = screen; + + if( op == poke ) while( i-- ) *p++ |= *q++; + else if( op == wipe ) while( i-- ) *p++ &= ~(*q++); + else while( i-- ) *p++ ^= *q++; +} + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Doggy/doggy.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,281 @@ +/* mbed DogM Graphic Display Library + * Copyright (c) 2011 Bernard Escaillas (www.midimetric.com) + */ + +#ifndef DOGGY_H +#define DOGGY_H + +#include "mbed.h" +#include "globaldefs.h" +#include "xfont.h" +#include "xfont_8.h" +#include "xfont_11.h" +#include "patterns.h" + +/// DOGM LCD control class +/// +/// Simple drawing and text rendering functions for DOGM-6 LCD +/// It should work also with the DOGL. +/// It does not handles up side down display. +/// +/// DogM circuit used in the example: +/// +/// 1/ LCD accesseories: +/// +/// - LCD is powered from the 3.3V of the mbed. This configuration requires 9 x 1 uF capacitors as +/// shown in the DogM datasheet. Personnaly i used 0.820 uF (or code 824) because i did not have 1 uFs... +/// - Amber backlight requires resistors. The data sheet mentions 3 x 47 Ohms resitors (one on each led). +/// actually, i added a 500 ohms pot and a 47 Ohms in serie to allow for backlight attenuation (and to +/// extend its lifetime. Also, drawing too much current from the mbed 'steels' power from the LCD and +/// reduces contrast... +/// +/// 2/ mbed connection: +/// +/// - dogm 40 (CS) --> mbed p8 +/// - dogm 39 (Reset) --> +3.3V (always off to save one pin) +/// - dogm 38 (A0) --> mbed p6 (unused miso pin) +/// - dogm 37 (SCLK) --> mbed p7 (SPI clock) +/// - dogm 36 (SI) --> mbed p5 (MOSI) +/// - dogm 35 (VDD) --> +3.3V +/// - dogm 34 (VVD2) --> +3.3V +/// - dogm 33 (VSS) --> GND +/// - dogm 32 to 21, see datasheet for condensers connection +/// +/// 3/ SPI cnofiguration: +/// +/// The datasheet states that the DogM handles data rates up to 10MHz +/// This rate is probably achieved with independant current source for the backlight. +/// This library uses by default a 1 MHz for the one time initialization (in case mbed +/// is powering up also and current is not yet fully stabilized) +/// It uses a 5MHz rate for work screen transfer. +/// You can change this by modifying the #DEFINE DOGMLC_MHZ 5000000 +/// (use the #undef / #define pair in your code to redefine this constant) +/// Increase the value to achieve faster transmission. +/// Lower the value if some messages are lost. +/// +/// Example: +/// @code +/// #include "mbed.h" +/// #include "doggy.h" +/// +/// SPI spi( p5, NC, p7 ); // MOSI, MISCO, CLK +/// DogMLCD dog( spi, p8, p6 ); // SPI, CS, A0 +/// +/// int main() +/// { +/// // select font to use: +/// dog.XFont = xfont_11; +/// +/// // transmit currently empty work screen (to clear physical display): +/// dog.Flush(); +/// +/// // create text with symbols: +/// char formula[] = { 159, '(', 'x', ')', '=', '2', 227, '+', 's', 'i', 'n', '(', 224, ')', '/', 251, 'x' }; +/// // output text from point(0,0): +/// dog.XString( 0, 0, formula ); +/// +/// // create text with variables and ouput from point (0,11): +/// char buf[256]; +/// sprintf( buf, "%s=%f", "A", 15.894 ); +/// dog.XString( 0, 11, buf ); +/// +/// // paint rectangles with built-in patterns: +/// dog.Rect( 0, 48, 15, 63, DOGMLCD_full ); +/// dog.Rect( 16, 48, 31, 63, DOGMLCD_dark ); +/// dog.Rect( 32, 48, 47, 63, DOGMLCD_grey ); +/// dog.Rect( 48, 48, 63, 63, DOGMLCD_lite ); +/// +/// // transmit work screen to physical screen: +/// dog.Flush(); +/// } +/// @endcode +class DogMLCD +{ +private: + char w_[1024]; // work screen + char* b_; // currently used screen + SPI& spi_; // attached SPI instance + DigitalOut cs_, a0_; // control pins + +public: + +// implementation in doggy.cpp: + + /// Xfont assignment, assign example: XFont = xfont_8; , values { xfont_8 (default), xfont_11 } + const XGlyph* XFont; + + /// Create DogMLCD instance and intialize display + /// + /// @param spi Instance object of an initialized SPI port (see SPI library) + /// @param cs Digital pin output to activate slave SPI + /// @param a0 Digital pin output to switch DogM from command mode to data mode + DogMLCD( SPI& spi, PinName cs, PinName a0 ); + + /// Use custom screen buffer + /// + /// @param screen pointer to an array of 1024 chars (128 colonnes of 8 pages) + void AttachScreen( char* screen ); + + /// Stop using custom screen buffer (revet to internal work screen) + void DetachScreen(); + + /// Activate pixel + /// + /// @param x horizontal coordinate from 0 to 127 included + /// @param y vertical coordinate from 0 to 63 + void Poke( int x, int y ); + + /// Clear pixel + /// + /// @param x horizontal coordinate from 0 to 127 included + /// @param y vertical coordinate from 0 to 63 included + void Wipe( int x, int y ); + + /// Invert pixel + /// + /// @param x horizontal coordinate from 0 to 127 included + /// @param y vertical coordinate from 0 to 63 included + void Inv( int x, int y ); + + /// Invert a rectangle of pixel + /// + void InvRect( int x0, int y0, int x1, int y1 ); + + /// Clear virtual screen + /// + /// Note : to clear only a part of the screen, use Rect( ..., DOGMLCD_full, wipe ); + void Clear(); + + /// Transmit virtual screen to physical display + /// + /// note: this is the more time consuming method, it should take about 3ms under normal conditions. + /// For faster transmit you can limit it to the part of the screen that has effectively changed + /// with Flush(page) or Flush(y0,y1) + void Flush(); + + /// Transmit one virtual screen page (or part of it) to physical display + /// + /// Physical screen is organized into 8 horizontal bands called pages. Each band is 8 lines high. + /// @param page number of the page to transmit, from 0 to 7. + /// @param x0 horizontal coordinate of first pixel to transmit, from 0 to 127. + /// @param x1 horizontal coordinate of last pixel to transmit, from 0 to 127. + void Flush( unsigned char page, int x0 = 0, int x1 = 127 ); + + /// Transmit several pages of the virtual screen to physical display + /// + /// Physical screen is organized into 8 horizontal bands called pages. Each band is 8 lines high. + /// Call time is about 150 us + 400 us per page at 5MHz spi frequency + /// @param page0 number of the first page to transmit, from 0 to 7. + /// @param page1 number of the last page to transmit, from 1 to 7 (0 means ignore argument). + void Page( unsigned char page0, unsigned char page1 = 0 ); + + /// Paste a custom screen over the internal work screen using raster op + /// + /// @param screen pointer to a custom screen made of 1024 chars + /// @param op raster operation, can be { poke(default), wipe, inv } + void Paste( char* screen, doggy_op op = poke ); + +// implementation in draw2D.cpp: + + /// Draw an horizontal line + /// + /// @param x0 left coordinate from 0 to 127 included + /// @param y vertical coordinate from 0 to 63 included + /// @param x1 right coordinate from 0 to 127 included + /// @param op bit math operation (raster), values { poke (default), wipe, inv } + void LineH( int x0, int y, int x1, doggy_op op = poke ); + + /// Draw a vertical line + /// + /// @param x horizontal coordinate from 0 to 127 included + /// @param y0 top coordinate from 0 to 63 included + /// @param y1 bottom coordinate from 0 to 63 included + /// @param op bit math operation (raster), values { poke (default), wipe, inv } + void LineV( int x, int y0, int y1, doggy_op op = poke ); + + /// Draw an diagonal line + /// + /// @param x0 start horizontal coordinate from 0 to 127 included + /// @param y0 start vertical coordinate from 0 to 63 included + /// @param x1 end horizontal coordinate from 0 to 127 included + /// @param y1 end vertical coordinate from 0 to 63 included + void Line( int x0, int y0, int x1, int y1, doggy_op = poke ); + + /// Draw an empty rectangle by combining 2 LineH and 2 LineV calls + /// + /// @param x0 top left corner, horizontal coordinate from 0 to 127 included + /// @param y0 top left corner, vertical coordinate from 0 to 63 included + /// @param x1 bottom right corner, horizontal coordinate from 0 to 127 included + /// @param y1 bottom right corner, vertical coordinate from 0 to 63 included + /// @param op bit math operation (raster), values { poke (default), wipe, inv } + void Frame( int x0, int y0, int x1, int y1, doggy_op op = poke ); + + /// Draw a filled rectangle by applying bitmap patterns + /// + /// Check patterns.h for built-in patterns names. + /// Use your own pattern by passing (const unsigned char[]){ col 1, col 2...,col 8 } + /// + /// @param x0 top left corner, horizontal coordinate from 0 to 127 included + /// @param y0 top left corner, vertical coordinate from 0 to 63 included + /// @param x1 bottom right corner, horizontal coordinate from 0 to 127 included + /// @param y1 bottom right corner, vertical coordinate from 0 to 63 included + /// @param pattern a 8x8 bitmap pattern defined by an array of 8 chars + /// @param op bit math operation (raster), values { poke (default), wipe, inv } + void Rect( int x0, int y0, int x1, int y0, const unsigned char* pattern = DOGMLCD_full, doggy_op op = poke ); + +// Implementation in xchar.cpp: + + /// Returns the XGlyph structure describing a single character bitmap + /// + /// If code is not found in the font, returns the character of code 0 (an empty square) + /// + /// @param code character code 0, 32 ~ 255 (xfont actually implements the extended US ascii character set) + /// @return an XGlyph structure { code, width, height, ...crening..., ...bitmap chars... } + XGlyph GetGlyph( int code ); + + /// Draw a XFont style character at position (x,y) + /// + /// @param x top left corner, horizontal coordinate from 0 to 127 included + /// @param y top left corner, vertical coordinate from 0 to 63 included + /// @param code US extended ascii code + /// @param op bottom right corner, vertical coordinate from 0 to 63 included + void XChar( int x, int y, int code, doggy_op op = poke ); + + /// Draw a XFont style character at position (x,y) + /// + /// @param x top left corner, horizontal coordinate from 0 to 127 included + /// @param y top left corner, vertical coordinate from 0 to 63 included + /// @param f Xglyph structure of the character + /// @param op bit math operation (raster), values { poke (default), wipe, inv } + void XChar( int x, int y, XGlyph f, doggy_op op = poke ); + + /// Draw a XFont style sequence of characters starting at position (x,y) + /// + /// Proportional font : Xfonts are proportionnal : i.e. not all characters have the same width. + /// + /// Crening (of Kerning): in most cases, there is a character spacing of one pixel beetween chars. + /// But some character combinations allow space saving. For instance, "T.", T followed by dot does not need + /// the extra pixel to ensure characters are not touching each other. Same for "aV" or "L'" or "=1" . + /// + /// New line: string can contain the new line '\\n' or (13) + /// + /// Wrapping: if the ouput reaches the right side of the screen, it will wrap to next line at position x. + /// wrapping is not space dependant, it happens anywhere in the string (inside words) + /// if wrapped line happens to begins with a space, the space is skipped + /// + /// @param x top left corner, horizontal coordinate from 0 to 127 included + /// @param y top left corner, vertical coordinate from 0 to 63 included + /// @param f Xglyph structure of the character + /// @param op bit math operation (raster), values { poke (default), wipe, inv } + /// + /// @return the last y coordinate used to output chars (may be different than initial argument if string was wrapped) + int XString( int x, int y, const char* s, doggy_op op = poke ); + int XString( int x, int y, int i, doggy_op = poke ); + int XString( int x, int y, float f, doggy_op = poke ); +}; + +/// Type definition for RasterOp +/// +/// is a pointer to a metthod of DogMLCD taking two int arguments +typedef void (DogMLCD::*RasterOp)(int,int); +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Doggy/draw2D.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,101 @@ +#include "doggy.h" + +void DogMLCD::LineH( int x0, int y, int x1, doggy_op raster ) +{ + if( y & 0xFFC0 ) return; // line is out of screen + BOUND( x0, 0, 127 ) + BOUND( x1, 0, 127 ) + ORDER( x0, x1 ) + + int n = x1 - x0 + 1; + char* p = b_ + (( y & 0x38 ) << 4) + x0; + if( raster == poke ) + { + char b = DOGMLCD_on[ y & 7 ]; + while( n-- ) + *p++ |= b; + } + else if( raster == wipe ) + { + char b = DOGMLCD_off[ y & 7 ]; + while( n-- ) + *p++ &= b; + } + else + { + char b = DOGMLCD_on[ y & 7 ]; + while( n-- ) + *p++ ^= b; + } +} +void DogMLCD::LineV( int x, int y0, int y1, doggy_op raster ) +{ + if( x & 0xFF80 ) return; // line is out of screen + BOUND( y0, 0, 63 ) + BOUND( y1, 0, 63 ) + ORDER( y0, y1 ) + RasterOp op = ((RasterOp[]){ &DogMLCD::Poke, &DogMLCD::Wipe, &DogMLCD::Inv })[raster]; + for( int y = y0 ; y <= y1 ; y++ ) + (this->*op)( x, y ); +} +void DogMLCD::Line( int x0, int y0, int x1, int y1, doggy_op raster ) +{ + bool steep = abs( y1 - y0 ) > abs( x1 - x0 ); + if( steep ) { SWAP( x0, y0 ) SWAP( x1, y1 ) } + if( x0 > x1) { SWAP( x0, x1 ) SWAP( y0, y1 ) } + + int dx = x1 - x0; + int dy = abs( y1 - y0 ); + int e = dx / 2; + int ystep = y0 < y1 ? 1 : -1; + RasterOp op = ((RasterOp[]){ &DogMLCD::Poke, &DogMLCD::Wipe, &DogMLCD::Inv })[raster]; + + if( steep ) for( int x = x0, y = y0 ; x <= x1 ; x++ ) + { + (this->*op)( y, x ); + if( ( e -= dy ) < 0 ) + { + y += ystep; + e += dx; + } + } + else for( int x = x0, y = y0 ; x <= x1 ; x++ ) + { + (this->*op)( x, y ); + if( ( e -= dy ) < 0 ) + { + y += ystep; + e += dx; + } + } +} +void DogMLCD::Frame( int x0, int y0, int x1, int y1, doggy_op raster ) +{ + ORDER( x0, x1 ) + ORDER( y0, y1 ) + + LineH( x0, y0, x1, raster ); + if( y1 > y0 ) LineH( x0, y1, x1, raster ); + + y0++; // don't overlap at angles + y1--; + if( y1 >= y0 ) // don't overlap if horizontal lines where adjacent + { + LineV( x0, y0, y1, raster ); + if( x1 > x0 ) LineV( x1, y0, y1, raster ); + } +} +void DogMLCD::Rect( int x0, int y0, int x1, int y1, const unsigned char* p, doggy_op raster ) +{ + BOUND( x0, 0, 127 ) + BOUND( x1, 0, 127 ) + BOUND( y0, 0, 63 ) + BOUND( y1, 0, 63 ) + ORDER( x0, x1 ) + ORDER( y0, y1 ) + RasterOp op = ((RasterOp[]){ &DogMLCD::Poke, &DogMLCD::Wipe, &DogMLCD::Inv })[raster]; + for( int x = x0 ; x <= x1 ; x++ ) + for( int y = y0 ; y <= y1 ; y++ ) + if( p[x & 7] & ( 1 << ( y & 7 ) ) ) + (this->*op)( x, y ); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Doggy/globaldefs.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,25 @@ +#ifndef GLOBALDEFS_H +#define GLOBALDEFS_H + +/// SPI frequency for method DogMLCD::Flush() +#define DOGMLCD_MHZ 18000000 +// Wait time after changing state of A0 in uS +#define DOGMLCD_TIME 8 + +#ifndef BOUND + #define BOUND(a,b,c) if( a < b ) a = b; else if( a > c ) a = c; +#endif +#ifndef SWAP + #define SWAP(a,b) { int c = a; a = b; b = c; } +#endif +#ifndef ORDER + #define ORDER(a,b) if( a > b ) { int c = a; a = b; b = c; } +#endif + +const unsigned char DOGMLCD_on[] = { 1, 2, 4, 8, 16, 32, 64, 128 }; +const unsigned char DOGMLCD_off[]= { 254, 253, 251, 247, 239, 223, 191, 127 }; + +/// Bit mpath operation (raster) +typedef enum{ poke, wipe, inv } doggy_op; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Doggy/patterns.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,17 @@ +#ifndef PATTERNS_H +#define PATTERNS_H + +const unsigned char DOGMLCD_full[] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF }; +const unsigned char DOGMLCD_dark[] = { 0xFF,0x55,0xFF,0x55,0xFF,0x55,0xFF,0x55 }; +const unsigned char DOGMLCD_grey[] = { 0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA }; +const unsigned char DOGMLCD_lite[] = { 0x55,0x00,0x55,0x00,0x55,0x00,0x55,0x00 }; +const unsigned char DOGMLCD_void[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; +const unsigned char DOGMLCD_bars[] = { 0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00 }; +const unsigned char DOGMLCD_lito[] = { 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55 }; +const unsigned char DOGMLCD_wave[] = { 0x11,0x88,0x44,0x88,0x11,0x22,0x44,0x22 }; +const unsigned char DOGMLCD_diag[] = { 0x88,0x44,0x22,0x11,0x88,0x44,0x22,0x11 }; +const unsigned char DOGMLCD_slah[] = { 0x11,0x22,0x44,0x88,0x11,0x22,0x44,0x88 }; +const unsigned char DOGMLCD_cros[] = { 0x55,0x22,0x55,0x88,0x55,0x22,0x55,0x88 }; +const unsigned char DOGMLCD_grek[] = { 0x80,0xFE,0x02,0xFA,0x8A,0xBA,0xA2,0xBE }; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Doggy/xchar.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,90 @@ +#include "doggy.h" + +XGlyph DogMLCD::GetGlyph( int code ) +{ + if( code > 31 && code < 256 ) + return XFont[code - 31]; + return XFont[0]; +} + +void DogMLCD::XChar( int x, int y, int code, doggy_op raster ) +{ + XChar( x, y, GetGlyph( code ) ); +} +void DogMLCD::XChar( int x, int y, XGlyph f, doggy_op raster ) +{ + const char* p = f.bmp; + RasterOp op = ((RasterOp[]){ &DogMLCD::Poke, &DogMLCD::Wipe, &DogMLCD::Inv })[raster]; + int y1 = y + f.hei; + for( int w = 0 ; w < f.wid ; w++ ) + { + for( int z = y, m = 1 ; z < y1 ; z++ ) + { + if( m == 256 ) { m = 1; p++; } + if( *p & m ) + (this->*op)( x, z ); + m <<= 1; + } + p++; + x++; + } +} +int DogMLCD::XString( int x, int y, int i, doggy_op raster ) +{ + char buf[32]; + sprintf( buf, "%d", i ); + return XString( x, y, buf, raster ); +} +int DogMLCD::XString( int x, int y, float f, doggy_op raster ) +{ + char buf[32]; + sprintf( buf, "%f", f ); + return XString( x, y, buf, raster ); +} +int DogMLCD::XString( int x, int y, const char* s, doggy_op raster ) +{ + int oldx = x; + int trc = 0, brc = 0, inter = XFont[0].hei; + while( *s ) + { + if( *s == 13 ) + { + x = oldx; + y += inter; + } + else if( *s > 31 ) + { + XGlyph f = GetGlyph( *s ); + + while( ( x > 0 ) && ( trc + f.tlc ) > 0 && ( brc + f.blc ) > 0 ) + { + x--; + trc--; + brc--; + } + + if( x + f.wid > 128 ) // simplified form of [ x + f.wid - 1 > 127 ] + { + x = oldx; + y += inter; + if( *s != 32 ) // don't ouput begining space on new line + { + XChar( x, y, f, raster ); + x += f.wid + 1; + } + } + else + { + XChar( x, y, f, raster ); + x += f.wid + 1; + } + if( *s != 32 ) // for space keep crening of previous char + { + trc = f.trc; + brc = f.brc; + } + } + s++; + } + return y; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Doggy/xfont.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,15 @@ +#ifndef FONT_H +#define FONT_H + +typedef struct { + unsigned char cod; // unicode value + unsigned char wid; // data width in pixels + unsigned char hei; // data height in pixels (multiple of 8) + unsigned char tlc; // form allows left top crening + unsigned char trc; // form allows right top crening + unsigned char blc; // form allows left bottom crening + unsigned char brc; // form allows right bottom crening + const char* bmp; +} XGlyph; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Doggy/xfont_11.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,231 @@ +#ifndef XFONT_11_H +#define XFONT_11_H + +const XGlyph xfont_11[] = { + { 0, 6, 11, 0, 0, 0, 0, (const char[]){ 0xFF, 0x03, 0x10, 0x02, 0x10, 0x02, 0x10, 0x02, 0x10, 0x02, 0xFF, 0x03 } }, + { 32, 2, 11, 0, 0, 0, 0, (const char[]){ 0x00, 0x00, 0x00, 0x00 } }, + { 33, 2, 11, 0, 0, 0, 0, (const char[]){ 0xBE, 0x01, 0xBE, 0x01 } }, + { 34, 5, 11, 0, 0, 1, 1, (const char[]){ 0x0E, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x06, 0x00 } }, + { 35, 7, 11, 0, 0, 0, 0, (const char[]){ 0x50, 0x00, 0xFC, 0x01, 0xFC, 0x01, 0x50, 0x00, 0xFC, 0x01, 0xFC, 0x01, 0x50, 0x00 } }, + { 36, 7, 11, 0, 0, 0, 0, (const char[]){ 0x98, 0x00, 0xBC, 0x01, 0x24, 0x01, 0xFE, 0x03, 0x24, 0x01, 0xEC, 0x01, 0xC8, 0x00 } }, + { 37, 8, 11, 0, 0, 0, 0, (const char[]){ 0x0C, 0x01, 0x9E, 0x00, 0x52, 0x00, 0xFE, 0x00, 0xFC, 0x01, 0x28, 0x01, 0xE4, 0x01, 0xC2, 0x00 } }, + { 38, 7, 11, 0, 0, 0, 0, (const char[]){ 0xC8, 0x00, 0xFC, 0x01, 0x34, 0x01, 0x7C, 0x01, 0xC8, 0x01, 0xA0, 0x01, 0x20, 0x01 } }, + { 39, 2, 11, 0, 0, 1, 1, (const char[]){ 0x0E, 0x00, 0x06, 0x00 } }, + { 40, 4, 11, 0, 0, 0, 0, (const char[]){ 0xFC, 0x00, 0xFE, 0x01, 0x03, 0x03, 0x01, 0x02 } }, + { 41, 4, 11, 0, 0, 0, 0, (const char[]){ 0x01, 0x02, 0x03, 0x03, 0xFE, 0x01, 0xFC, 0x00 } }, + { 42, 6, 11, 0, 0, 0, 0, (const char[]){ 0x50, 0x00, 0x20, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0x20, 0x00, 0x50, 0x00 } }, + { 43, 6, 11, 0, 0, 0, 0, (const char[]){ 0x20, 0x00, 0x20, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0x20, 0x00, 0x20, 0x00 } }, + { 44, 3, 11, 1, 1, 0, 0, (const char[]){ 0x00, 0x04, 0x80, 0x03, 0x80, 0x01 } }, + { 45, 6, 11, 1, 1, 0, 0, (const char[]){ 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00 } }, + { 46, 2, 11, 2, 2, 0, 0, (const char[]){ 0x80, 0x01, 0x80, 0x01 } }, + { 47, 5, 11, 1, 0, 0, 1, (const char[]){ 0x00, 0x07, 0xC0, 0x01, 0x70, 0x00, 0x1C, 0x00, 0x07, 0x00 } }, + { 48, 6, 11, 0, 0, 0, 0, (const char[]){ 0xFC, 0x00, 0xFE, 0x01, 0x02, 0x01, 0x02, 0x01, 0xFE, 0x01, 0xFC, 0x00 } }, + { 49, 4, 11, 0, 0, 1, 0, (const char[]){ 0x04, 0x00, 0x04, 0x00, 0xFE, 0x01, 0xFE, 0x01 } }, + { 50, 6, 11, 0, 0, 0, 0, (const char[]){ 0x8C, 0x01, 0xCE, 0x01, 0x62, 0x01, 0x32, 0x01, 0x1E, 0x01, 0x0C, 0x01 } }, + { 51, 6, 11, 0, 0, 0, 0, (const char[]){ 0x84, 0x00, 0x86, 0x01, 0x12, 0x01, 0x12, 0x01, 0xFE, 0x01, 0xEC, 0x00 } }, + { 52, 6, 11, 0, 0, 0, 0, (const char[]){ 0x70, 0x00, 0x48, 0x00, 0x44, 0x00, 0xFE, 0x01, 0xFE, 0x01, 0x40, 0x00 } }, + { 53, 6, 11, 0, 0, 0, 0, (const char[]){ 0xDE, 0x00, 0xDE, 0x01, 0x12, 0x01, 0x12, 0x01, 0xF2, 0x01, 0xE2, 0x00 } }, + { 54, 6, 11, 0, 0, 0, 0, (const char[]){ 0xF8, 0x00, 0xFC, 0x01, 0x12, 0x01, 0x12, 0x01, 0xF2, 0x01, 0xE0, 0x00 } }, + { 55, 6, 11, 0, 0, 0, 0, (const char[]){ 0x02, 0x00, 0x82, 0x01, 0xE2, 0x01, 0x7A, 0x00, 0x1E, 0x00, 0x06, 0x00 } }, + { 56, 6, 11, 0, 0, 0, 0, (const char[]){ 0xEC, 0x00, 0xFE, 0x01, 0x12, 0x01, 0x12, 0x01, 0xFE, 0x01, 0xEC, 0x00 } }, + { 57, 6, 11, 0, 0, 0, 0, (const char[]){ 0x1C, 0x00, 0x3E, 0x01, 0x22, 0x01, 0xA2, 0x01, 0xFE, 0x00, 0x7C, 0x00 } }, + { 58, 2, 11, 0, 0, 0, 0, (const char[]){ 0x98, 0x01, 0x98, 0x01 } }, + { 59, 3, 11, 0, 0, 0, 0, (const char[]){ 0x00, 0x04, 0x98, 0x03, 0x98, 0x01 } }, + { 60, 5, 11, 0, 0, 0, 0, (const char[]){ 0x20, 0x00, 0x70, 0x00, 0xD8, 0x00, 0x8C, 0x01, 0x04, 0x01 } }, + { 61, 6, 11, 1, 1, 0, 0, (const char[]){ 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00 } }, + { 62, 5, 11, 0, 0, 0, 0, (const char[]){ 0x04, 0x01, 0x8C, 0x01, 0xD8, 0x00, 0x70, 0x00, 0x20, 0x00 } }, + { 63, 6, 11, 0, 0, 0, 0, (const char[]){ 0x04, 0x00, 0x06, 0x00, 0xA2, 0x01, 0xB2, 0x01, 0x1E, 0x00, 0x0C, 0x00 } }, + { 64, 8, 11, 0, 0, 0, 0, (const char[]){ 0x78, 0x00, 0x84, 0x00, 0x32, 0x01, 0x4A, 0x01, 0x4A, 0x01, 0x7A, 0x01, 0x42, 0x00, 0x7C, 0x00 } }, + { 65, 7, 11, 0, 0, 0, 0, (const char[]){ 0xFC, 0x01, 0xFE, 0x01, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0xFE, 0x01, 0xFC, 0x01 } }, + { 66, 7, 11, 0, 0, 0, 0, (const char[]){ 0xFE, 0x01, 0xFE, 0x01, 0x12, 0x01, 0x12, 0x01, 0x12, 0x01, 0xFE, 0x01, 0xEC, 0x00 } }, + { 67, 7, 11, 0, 0, 0, 0, (const char[]){ 0xFC, 0x00, 0xFE, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x86, 0x01, 0x84, 0x00 } }, + { 68, 7, 11, 0, 0, 0, 0, (const char[]){ 0xFE, 0x01, 0xFE, 0x01, 0x02, 0x01, 0x02, 0x01, 0x06, 0x01, 0xFC, 0x01, 0xF8, 0x00 } }, + { 69, 7, 11, 0, 0, 0, 0, (const char[]){ 0xFE, 0x01, 0xFE, 0x01, 0x12, 0x01, 0x12, 0x01, 0x12, 0x01, 0x02, 0x01, 0x02, 0x01 } }, + { 70, 7, 11, 0, 0, 0, 2, (const char[]){ 0xFE, 0x01, 0xFE, 0x01, 0x12, 0x00, 0x12, 0x00, 0x12, 0x00, 0x02, 0x00, 0x02, 0x00 } }, + { 71, 7, 11, 0, 0, 0, 0, (const char[]){ 0xFC, 0x00, 0xFE, 0x01, 0x02, 0x01, 0x02, 0x01, 0x22, 0x01, 0xE6, 0x01, 0xE4, 0x00 } }, + { 72, 7, 11, 0, 0, 0, 0, (const char[]){ 0xFE, 0x01, 0xFE, 0x01, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0xFE, 0x01, 0xFE, 0x01 } }, + { 73, 4, 11, 0, 0, 0, 0, (const char[]){ 0x02, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0x02, 0x01 } }, + { 74, 6, 11, 1, 0, 0, 0, (const char[]){ 0xC0, 0x00, 0xC0, 0x01, 0x02, 0x01, 0xFE, 0x01, 0xFE, 0x00, 0x02, 0x00 } }, + { 75, 7, 11, 0, 0, 0, 0, (const char[]){ 0xFE, 0x01, 0xFE, 0x01, 0x30, 0x00, 0x78, 0x00, 0xCC, 0x00, 0x86, 0x01, 0x02, 0x01 } }, + { 76, 6, 11, 0, 2, 0, 0, (const char[]){ 0xFE, 0x01, 0xFE, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01 } }, + { 77, 8, 11, 0, 0, 0, 0, (const char[]){ 0xFE, 0x01, 0xFE, 0x01, 0x0C, 0x00, 0x18, 0x00, 0x18, 0x00, 0x0C, 0x00, 0xFE, 0x01, 0xFE, 0x01 } }, + { 78, 8, 11, 0, 0, 0, 0, (const char[]){ 0xFE, 0x01, 0xFE, 0x01, 0x06, 0x00, 0x18, 0x00, 0x60, 0x00, 0x80, 0x01, 0xFE, 0x01, 0xFE, 0x01 } }, + { 79, 7, 11, 0, 0, 0, 0, (const char[]){ 0xFC, 0x00, 0xFE, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0xFE, 0x01, 0xFC, 0x00 } }, + { 80, 7, 11, 0, 0, 0, 1, (const char[]){ 0xFE, 0x01, 0xFE, 0x01, 0x42, 0x00, 0x42, 0x00, 0x42, 0x00, 0x7E, 0x00, 0x3C, 0x00 } }, + { 81, 7, 11, 0, 0, 0, 0, (const char[]){ 0xFC, 0x00, 0xFE, 0x01, 0x02, 0x01, 0x42, 0x01, 0x82, 0x01, 0xFE, 0x03, 0xFC, 0x02 } }, + { 82, 7, 11, 0, 0, 0, 0, (const char[]){ 0xFE, 0x01, 0xFE, 0x01, 0x42, 0x00, 0x42, 0x00, 0xC2, 0x00, 0x7E, 0x01, 0x3C, 0x01 } }, + { 83, 7, 11, 0, 0, 0, 0, (const char[]){ 0x8C, 0x00, 0x9E, 0x01, 0x12, 0x01, 0x32, 0x01, 0x22, 0x01, 0xE6, 0x01, 0xC4, 0x00 } }, + { 84, 6, 11, 0, 0, 2, 2, (const char[]){ 0x02, 0x00, 0x02, 0x00, 0xFE, 0x01, 0xFE, 0x01, 0x02, 0x00, 0x02, 0x00 } }, + { 85, 7, 11, 0, 0, 0, 0, (const char[]){ 0xFE, 0x00, 0xFE, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xFE, 0x01, 0xFE, 0x00 } }, + { 86, 8, 11, 0, 0, 0, 0, (const char[]){ 0x0E, 0x00, 0x7E, 0x00, 0xF0, 0x01, 0x80, 0x01, 0x80, 0x01, 0xF0, 0x01, 0x7E, 0x00, 0x0E, 0x00 } }, + { 87, 8, 11, 0, 0, 0, 0, (const char[]){ 0x7E, 0x00, 0xFE, 0x01, 0x80, 0x01, 0xF0, 0x00, 0xF0, 0x00, 0x80, 0x01, 0xFE, 0x01, 0xFE, 0x00 } }, + { 88, 7, 11, 0, 0, 0, 0, (const char[]){ 0x86, 0x01, 0xCE, 0x01, 0x78, 0x00, 0x30, 0x00, 0x78, 0x00, 0xCE, 0x01, 0x86, 0x01 } }, + { 89, 6, 11, 0, 0, 1, 1, (const char[]){ 0x1E, 0x00, 0x3E, 0x00, 0xE0, 0x01, 0xE0, 0x01, 0x3E, 0x00, 0x1E, 0x00 } }, + { 90, 7, 11, 0, 0, 0, 0, (const char[]){ 0x82, 0x01, 0xC2, 0x01, 0x62, 0x01, 0x32, 0x01, 0x1A, 0x01, 0x0E, 0x01, 0x06, 0x01 } }, + { 91, 4, 11, 0, 0, 0, 0, (const char[]){ 0xFF, 0x03, 0xFF, 0x03, 0x01, 0x02, 0x01, 0x02 } }, + { 92, 5, 11, 0, 1, 0, 0, (const char[]){ 0x06, 0x00, 0x1E, 0x00, 0x78, 0x00, 0xE0, 0x01, 0x80, 0x01 } }, + { 93, 4, 11, 0, 0, 0, 0, (const char[]){ 0x01, 0x02, 0x01, 0x02, 0xFF, 0x03, 0xFF, 0x03 } }, + { 94, 7, 11, 0, 0, 1, 1, (const char[]){ 0x08, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x03, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x08, 0x00 } }, + { 95, 6, 11, 1, 1, 0, 0, (const char[]){ 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01 } }, + { 96, 3, 11, 0, 0, 1, 1, (const char[]){ 0x06, 0x00, 0x0E, 0x00, 0x10, 0x00 } }, + { 97, 6, 11, 1, 0, 0, 0, (const char[]){ 0xC0, 0x00, 0xE8, 0x01, 0x28, 0x01, 0x28, 0x01, 0xF8, 0x01, 0xF8, 0x01 } }, + { 98, 6, 11, 0, 1, 0, 0, (const char[]){ 0xFE, 0x01, 0xFE, 0x01, 0x08, 0x01, 0x08, 0x01, 0xF8, 0x01, 0xF0, 0x00 } }, + { 99, 6, 11, 1, 1, 0, 0, (const char[]){ 0xF0, 0x00, 0xF8, 0x01, 0x08, 0x01, 0x08, 0x01, 0x98, 0x01, 0x90, 0x00 } }, + { 100, 6, 11, 1, 0, 0, 0, (const char[]){ 0xF0, 0x00, 0xF8, 0x01, 0x08, 0x01, 0x08, 0x01, 0xFE, 0x01, 0xFE, 0x01 } }, + { 101, 6, 11, 1, 1, 0, 0, (const char[]){ 0xF0, 0x00, 0xF8, 0x01, 0x28, 0x01, 0x28, 0x01, 0xB8, 0x01, 0xB0, 0x00 } }, + { 102, 5, 11, 0, 0, 0, 1, (const char[]){ 0x08, 0x00, 0xFC, 0x01, 0xFE, 0x01, 0x0A, 0x00, 0x0A, 0x00 } }, + { 103, 5, 11, 1, 1, 0, 0, (const char[]){ 0xF0, 0x00, 0xF8, 0x05, 0x08, 0x05, 0xF8, 0x07, 0xF0, 0x03 } }, + { 104, 6, 11, 0, 1, 0, 0, (const char[]){ 0xFE, 0x01, 0xFE, 0x01, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x01, 0xF0, 0x01 } }, + { 105, 2, 11, 0, 0, 0, 0, (const char[]){ 0xFA, 0x01, 0xFA, 0x01 } }, + { 106, 3, 11, 1, 0, 0, 0, (const char[]){ 0x00, 0x04, 0xFA, 0x07, 0xFA, 0x03 } }, + { 107, 6, 11, 0, 1, 0, 0, (const char[]){ 0xFE, 0x01, 0xFE, 0x01, 0x20, 0x00, 0x70, 0x00, 0xD8, 0x01, 0x88, 0x01 } }, + { 108, 2, 11, 1, 1, 0, 0, (const char[]){ 0xFE, 0x01, 0xFE, 0x01 } }, + { 109, 8, 11, 0, 1, 1, 0, (const char[]){ 0xF0, 0x01, 0xF8, 0x01, 0x08, 0x00, 0xF8, 0x01, 0xF0, 0x01, 0x08, 0x00, 0xF8, 0x01, 0xF0, 0x01 } }, + { 110, 6, 11, 1, 1, 0, 0, (const char[]){ 0x08, 0x00, 0xF8, 0x01, 0xF8, 0x01, 0x08, 0x00, 0xF8, 0x01, 0xF0, 0x01 } }, + { 111, 6, 11, 0, 1, 0, 0, (const char[]){ 0xF0, 0x00, 0xF8, 0x01, 0x08, 0x01, 0x08, 0x01, 0xF8, 0x01, 0xF0, 0x00 } }, + { 112, 6, 11, 1, 0, 0, 0, (const char[]){ 0xF8, 0x07, 0xF8, 0x07, 0x08, 0x01, 0x08, 0x01, 0xF8, 0x01, 0xF0, 0x00 } }, + { 113, 6, 11, 0, 0, 0, 0, (const char[]){ 0xF0, 0x00, 0xF8, 0x01, 0x08, 0x01, 0x08, 0x01, 0xF8, 0x07, 0xF8, 0x07 } }, + { 114, 6, 11, 0, 0, 1, 0, (const char[]){ 0x08, 0x00, 0xF8, 0x01, 0xF0, 0x01, 0x08, 0x00, 0x38, 0x00, 0x30, 0x00 } }, + { 115, 5, 11, 0, 0, 0, 0, (const char[]){ 0x90, 0x00, 0xB8, 0x01, 0x68, 0x01, 0xD8, 0x01, 0x90, 0x00 } }, + { 116, 4, 11, 0, 0, 1, 0, (const char[]){ 0x08, 0x00, 0xFC, 0x00, 0xFE, 0x01, 0x08, 0x01 } }, + { 117, 6, 11, 0, 1, 0, 0, (const char[]){ 0xF8, 0x00, 0xF8, 0x01, 0x00, 0x01, 0xF8, 0x01, 0xF8, 0x01, 0x00, 0x01 } }, + { 118, 7, 11, 0, 0, 0, 0, (const char[]){ 0x18, 0x00, 0x78, 0x00, 0xE0, 0x00, 0x80, 0x01, 0xE0, 0x00, 0x78, 0x00, 0x18, 0x00 } }, + { 119, 8, 11, 0, 0, 0, 0, (const char[]){ 0xF8, 0x00, 0xF8, 0x01, 0x00, 0x01, 0xE0, 0x01, 0xE0, 0x01, 0x00, 0x01, 0xF8, 0x01, 0xF8, 0x00 } }, + { 120, 6, 11, 0, 0, 0, 0, (const char[]){ 0x08, 0x01, 0x98, 0x01, 0xF0, 0x00, 0xF0, 0x00, 0x98, 0x01, 0x08, 0x01 } }, + { 121, 5, 11, 0, 0, 0, 0, (const char[]){ 0xF8, 0x04, 0xF8, 0x05, 0x00, 0x05, 0xF8, 0x07, 0xF8, 0x03 } }, + { 122, 6, 11, 0, 0, 0, 0, (const char[]){ 0x88, 0x01, 0xC8, 0x01, 0xE8, 0x01, 0x78, 0x01, 0x38, 0x01, 0x18, 0x01 } }, + { 123, 4, 11, 0, 0, 0, 0, (const char[]){ 0x30, 0x00, 0xFE, 0x01, 0xCF, 0x03, 0x01, 0x02 } }, + { 124, 2, 11, 0, 0, 0, 0, (const char[]){ 0xFF, 0x01, 0xFF, 0x01 } }, + { 125, 4, 11, 0, 0, 0, 0, (const char[]){ 0x01, 0x02, 0xCF, 0x03, 0xFE, 0x01, 0x30, 0x00 } }, + { 126, 8, 11, 0, 0, 0, 0, (const char[]){ 0x30, 0x00, 0x38, 0x00, 0x08, 0x00, 0x38, 0x00, 0x70, 0x00, 0x40, 0x00, 0x70, 0x00, 0x30, 0x00 } }, + { 127, 6, 11, 0, 0, 0, 0, (const char[]){ 0x55, 0x01, 0xAA, 0x02, 0x55, 0x01, 0xAA, 0x02, 0x55, 0x01, 0xAA, 0x02 } }, + { 128, 7, 11, 0, 0, 0, 0, (const char[]){ 0xFC, 0x00, 0xFE, 0x01, 0x02, 0x05, 0x02, 0x07, 0x02, 0x03, 0x86, 0x01, 0x84, 0x00 } }, + { 129, 6, 11, 0, 1, 0, 0, (const char[]){ 0xF8, 0x00, 0xFA, 0x01, 0x00, 0x01, 0xFA, 0x01, 0xF8, 0x01, 0x00, 0x01 } }, + { 130, 6, 11, 0, 0, 0, 0, (const char[]){ 0xF0, 0x00, 0xF8, 0x01, 0x2A, 0x01, 0x29, 0x01, 0xB8, 0x01, 0xB0, 0x00 } }, + { 131, 6, 11, 0, 0, 0, 0, (const char[]){ 0xC0, 0x00, 0xEA, 0x01, 0x29, 0x01, 0x29, 0x01, 0xFA, 0x01, 0xF8, 0x01 } }, + { 132, 6, 11, 0, 0, 0, 0, (const char[]){ 0xC0, 0x00, 0xEA, 0x01, 0x28, 0x01, 0x28, 0x01, 0xFA, 0x01, 0xF8, 0x01 } }, + { 133, 6, 11, 0, 0, 0, 0, (const char[]){ 0xC0, 0x00, 0xE8, 0x01, 0x29, 0x01, 0x2A, 0x01, 0xF8, 0x01, 0xF8, 0x01 } }, + { 134, 6, 11, 0, 0, 0, 0, (const char[]){ 0xC0, 0x00, 0xE8, 0x01, 0x2A, 0x01, 0x2A, 0x01, 0xF8, 0x01, 0xF8, 0x01 } }, + { 135, 6, 11, 0, 0, 0, 0, (const char[]){ 0xF0, 0x00, 0xF8, 0x01, 0x08, 0x05, 0x08, 0x03, 0x98, 0x01, 0x90, 0x00 } }, + { 136, 6, 11, 0, 0, 0, 0, (const char[]){ 0xF0, 0x00, 0xFA, 0x01, 0x29, 0x01, 0x29, 0x01, 0xBA, 0x01, 0xB0, 0x00 } }, + { 137, 6, 11, 0, 0, 0, 0, (const char[]){ 0xF0, 0x00, 0xFA, 0x01, 0x28, 0x01, 0x28, 0x01, 0xBA, 0x01, 0xB0, 0x00 } }, + { 138, 6, 11, 0, 0, 0, 0, (const char[]){ 0xF0, 0x00, 0xF8, 0x01, 0x29, 0x01, 0x2A, 0x01, 0xB8, 0x01, 0xB0, 0x00 } }, + { 139, 4, 11, 0, 0, 0, 0, (const char[]){ 0x02, 0x00, 0xF8, 0x01, 0xF8, 0x01, 0x02, 0x00 } }, + { 140, 4, 11, 0, 0, 0, 0, (const char[]){ 0x02, 0x00, 0xF9, 0x01, 0xF9, 0x01, 0x02, 0x00 } }, + { 141, 2, 11, 0, 0, 0, 0, (const char[]){ 0xF9, 0x01, 0xFA, 0x01 } }, + { 142, 7, 11, 0, 0, 0, 0, (const char[]){ 0xFC, 0x01, 0xFE, 0x01, 0x43, 0x00, 0x42, 0x00, 0x43, 0x00, 0xFE, 0x01, 0xFC, 0x01 } }, + { 143, 7, 11, 0, 0, 0, 0, (const char[]){ 0xFC, 0x01, 0xFE, 0x01, 0x42, 0x00, 0x43, 0x00, 0x42, 0x00, 0xFE, 0x01, 0xFC, 0x01 } }, + { 144, 7, 11, 0, 0, 0, 0, (const char[]){ 0xFE, 0x01, 0xFE, 0x01, 0x12, 0x01, 0x12, 0x01, 0x13, 0x01, 0x03, 0x01, 0x02, 0x01 } }, + { 145, 8, 11, 1, 0, 0, 0, (const char[]){ 0xC0, 0x00, 0xE8, 0x01, 0x28, 0x01, 0xF0, 0x01, 0xF0, 0x01, 0x28, 0x01, 0x38, 0x01, 0xB0, 0x00 } }, + { 146, 9, 11, 0, 0, 0, 0, (const char[]){ 0xF8, 0x01, 0xFC, 0x01, 0x46, 0x00, 0x46, 0x00, 0xFE, 0x01, 0xFE, 0x01, 0x12, 0x01, 0x12, 0x01, 0x02, 0x01 } }, + { 147, 6, 11, 0, 0, 0, 0, (const char[]){ 0xF0, 0x00, 0xFA, 0x01, 0x09, 0x01, 0x09, 0x01, 0xFA, 0x01, 0xF0, 0x00 } }, + { 148, 6, 11, 0, 0, 0, 0, (const char[]){ 0xF0, 0x00, 0xFA, 0x01, 0x08, 0x01, 0x08, 0x01, 0xFA, 0x01, 0xF0, 0x00 } }, + { 149, 6, 11, 0, 0, 0, 0, (const char[]){ 0xF0, 0x00, 0xF8, 0x01, 0x09, 0x01, 0x0A, 0x01, 0xF8, 0x01, 0xF0, 0x00 } }, + { 150, 6, 11, 0, 1, 0, 0, (const char[]){ 0xF8, 0x00, 0xFA, 0x01, 0x01, 0x01, 0xFA, 0x01, 0xF8, 0x01, 0x00, 0x01 } }, + { 151, 6, 11, 0, 1, 0, 0, (const char[]){ 0xF8, 0x00, 0xF8, 0x01, 0x01, 0x01, 0xFA, 0x01, 0xF8, 0x01, 0x00, 0x01 } }, + { 152, 5, 11, 0, 0, 0, 0, (const char[]){ 0xF8, 0x04, 0xFA, 0x05, 0x00, 0x05, 0xFA, 0x07, 0xF8, 0x03 } }, + { 153, 7, 11, 0, 0, 0, 0, (const char[]){ 0xFC, 0x00, 0xFF, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0xFF, 0x01, 0xFC, 0x00 } }, + { 154, 7, 11, 0, 0, 0, 0, (const char[]){ 0xFE, 0x00, 0xFD, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xFD, 0x01, 0xFE, 0x00 } }, + { 155, 7, 11, 0, 0, 0, 0, (const char[]){ 0xF0, 0x00, 0xF8, 0x01, 0x08, 0x01, 0x0E, 0x07, 0x08, 0x01, 0x98, 0x01, 0x90, 0x00 } }, + { 156, 6, 11, 0, 0, 0, 0, (const char[]){ 0x14, 0x01, 0xFE, 0x01, 0xFA, 0x01, 0x12, 0x01, 0x06, 0x01, 0x04, 0x01 } }, + { 157, 7, 11, 0, 0, 0, 0, (const char[]){ 0x28, 0x00, 0x3E, 0x00, 0x7E, 0x00, 0xE8, 0x01, 0x7E, 0x00, 0x3E, 0x00, 0x28, 0x00 } }, + { 158, 7, 11, 0, 0, 0, 0, (const char[]){ 0x28, 0x00, 0xFC, 0x00, 0xEE, 0x01, 0x2A, 0x01, 0x2A, 0x01, 0x02, 0x01, 0x84, 0x00 } }, + { 159, 6, 11, 0, 0, 0, 1, (const char[]){ 0x10, 0x01, 0xFC, 0x01, 0xFE, 0x00, 0x12, 0x00, 0x06, 0x00, 0x04, 0x00 } }, + { 160, 6, 11, 0, 0, 0, 0, (const char[]){ 0xC0, 0x00, 0xE8, 0x01, 0x2A, 0x01, 0x29, 0x01, 0xF8, 0x01, 0xF8, 0x01 } }, + { 161, 2, 11, 0, 0, 0, 0, (const char[]){ 0xFA, 0x01, 0xF9, 0x01 } }, + { 162, 6, 11, 0, 0, 0, 0, (const char[]){ 0xF0, 0x00, 0xF8, 0x01, 0x0A, 0x01, 0x09, 0x01, 0xF8, 0x01, 0xF0, 0x00 } }, + { 163, 6, 11, 0, 0, 0, 0, (const char[]){ 0xF8, 0x00, 0xF8, 0x01, 0x02, 0x01, 0xF9, 0x01, 0xF8, 0x01, 0x00, 0x01 } }, + { 164, 6, 11, 0, 0, 0, 0, (const char[]){ 0x08, 0x00, 0xF9, 0x01, 0xF9, 0x01, 0x0A, 0x00, 0xFA, 0x01, 0xF0, 0x01 } }, + { 165, 8, 11, 0, 0, 0, 0, (const char[]){ 0xFE, 0x01, 0xFE, 0x01, 0x07, 0x00, 0x19, 0x00, 0x62, 0x00, 0x82, 0x01, 0xFE, 0x01, 0xFE, 0x01 } }, + { 166, 5, 11, 0, 0, 1, 1, (const char[]){ 0x06, 0x00, 0x0F, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x0E, 0x00 } }, + { 167, 5, 11, 0, 0, 1, 1, (const char[]){ 0x06, 0x00, 0x0F, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x06, 0x00 } }, + { 168, 6, 11, 1, 1, 0, 0, (const char[]){ 0x00, 0x03, 0x80, 0x07, 0xD8, 0x04, 0x58, 0x04, 0x00, 0x06, 0x00, 0x02 } }, + { 169, 6, 11, 0, 0, 0, 0, (const char[]){ 0xE0, 0x01, 0xE0, 0x01, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00 } }, + { 170, 6, 11, 0, 0, 0, 0, (const char[]){ 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xE0, 0x01, 0xE0, 0x01 } }, + { 171, 8, 11, 0, 0, 0, 0, (const char[]){ 0x9C, 0x00, 0xDC, 0x00, 0x60, 0x00, 0x30, 0x00, 0x58, 0x02, 0x2C, 0x03, 0xE4, 0x03, 0xC0, 0x02 } }, + { 172, 8, 11, 0, 0, 0, 0, (const char[]){ 0x9C, 0x00, 0xDC, 0x00, 0x60, 0x00, 0x30, 0x00, 0x98, 0x01, 0x4C, 0x01, 0xE4, 0x03, 0xE0, 0x03 } }, + { 173, 2, 11, 0, 0, 0, 0, (const char[]){ 0xFA, 0x03, 0xFA, 0x03 } }, + { 174, 7, 11, 0, 0, 0, 0, (const char[]){ 0x20, 0x00, 0x70, 0x00, 0xD8, 0x00, 0xAC, 0x01, 0x70, 0x00, 0xD8, 0x00, 0x8C, 0x01 } }, + { 175, 7, 11, 0, 0, 0, 0, (const char[]){ 0x8C, 0x01, 0xD8, 0x00, 0x70, 0x00, 0xAC, 0x01, 0xD8, 0x00, 0x70, 0x00, 0x20, 0x00 } }, + { 176, 4, 11, 0, 0, 0, 0, (const char[]){ 0x00, 0x00, 0x55, 0x05, 0x00, 0x00, 0xAA, 0x0A } }, + { 177, 4, 11, 0, 0, 0, 0, (const char[]){ 0x55, 0x05, 0xAA, 0x0A, 0x55, 0x05, 0xAA, 0x0A } }, + { 178, 4, 11, 0, 0, 0, 0, (const char[]){ 0xFF, 0x0F, 0xAA, 0x0A, 0xFF, 0x0F, 0x55, 0x05 } }, + { 179, 9, 11, 0, 0, 0, 0, (const char[]){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 180, 9, 11, 0, 0, 0, 0, (const char[]){ 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 181, 9, 11, 0, 0, 0, 0, (const char[]){ 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 182, 9, 11, 0, 0, 0, 0, (const char[]){ 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 183, 9, 11, 0, 0, 0, 0, (const char[]){ 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xE0, 0x0F, 0x20, 0x00, 0xE0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 184, 9, 11, 0, 0, 0, 0, (const char[]){ 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0xF0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 185, 9, 11, 0, 0, 0, 0, (const char[]){ 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0xDF, 0x0F, 0x00, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 186, 9, 11, 0, 0, 0, 0, (const char[]){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 187, 9, 11, 0, 0, 0, 0, (const char[]){ 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0xD0, 0x0F, 0x10, 0x00, 0xF0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 188, 9, 11, 0, 0, 0, 0, (const char[]){ 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x5F, 0x00, 0x40, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 189, 9, 11, 0, 0, 0, 0, (const char[]){ 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x3F, 0x00, 0x20, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 190, 9, 11, 0, 0, 0, 0, (const char[]){ 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 191, 9, 11, 0, 0, 0, 0, (const char[]){ 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xE0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 192, 9, 11, 0, 0, 0, 0, (const char[]){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00 } }, + { 193, 9, 11, 0, 0, 0, 0, (const char[]){ 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x3F, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00 } }, + { 194, 9, 11, 0, 0, 0, 0, (const char[]){ 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xE0, 0x0F, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00 } }, + { 195, 9, 11, 0, 0, 0, 0, (const char[]){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00 } }, + { 196, 9, 11, 0, 0, 0, 0, (const char[]){ 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00 } }, + { 197, 9, 11, 0, 0, 0, 0, (const char[]){ 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xFF, 0x0F, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00 } }, + { 198, 9, 11, 0, 0, 0, 0, (const char[]){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00 } }, + { 199, 9, 11, 0, 0, 0, 0, (const char[]){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0xFF, 0x0F, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00 } }, + { 200, 9, 11, 0, 0, 0, 0, (const char[]){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x40, 0x00, 0x5F, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00 } }, + { 201, 9, 11, 0, 0, 0, 0, (const char[]){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x0F, 0x10, 0x00, 0xD0, 0x0F, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00 } }, + { 202, 9, 11, 0, 0, 0, 0, (const char[]){ 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x5F, 0x00, 0x40, 0x00, 0x5F, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00 } }, + { 203, 9, 11, 0, 0, 0, 0, (const char[]){ 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0xD0, 0x0F, 0x10, 0x00, 0xD0, 0x0F, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00 } }, + { 204, 9, 11, 0, 0, 0, 0, (const char[]){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0x00, 0x00, 0xDF, 0x0F, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00 } }, + { 205, 9, 11, 0, 0, 0, 0, (const char[]){ 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00 } }, + { 206, 9, 11, 0, 0, 0, 0, (const char[]){ 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0xDF, 0x0F, 0x00, 0x00, 0xDF, 0x0F, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00 } }, + { 207, 9, 11, 0, 0, 0, 0, (const char[]){ 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x5F, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00 } }, + { 208, 9, 11, 0, 0, 0, 0, (const char[]){ 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x3F, 0x00, 0x20, 0x00, 0x3F, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00 } }, + { 209, 9, 11, 0, 0, 0, 0, (const char[]){ 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0xD0, 0x0F, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00 } }, + { 210, 9, 11, 0, 0, 0, 0, (const char[]){ 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xE0, 0x0F, 0x20, 0x00, 0xE0, 0x0F, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00 } }, + { 211, 9, 11, 0, 0, 0, 0, (const char[]){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x20, 0x00, 0x3F, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00 } }, + { 212, 9, 11, 0, 0, 0, 0, (const char[]){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00 } }, + { 213, 9, 11, 0, 0, 0, 0, (const char[]){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x0F, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00 } }, + { 214, 9, 11, 0, 0, 0, 0, (const char[]){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x0F, 0x20, 0x00, 0xE0, 0x0F, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00 } }, + { 215, 9, 11, 0, 0, 0, 0, (const char[]){ 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xFF, 0x0F, 0x20, 0x00, 0xFF, 0x0F, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00 } }, + { 216, 9, 11, 0, 0, 0, 0, (const char[]){ 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0xFF, 0x0F, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, 0x00 } }, + { 217, 9, 11, 0, 0, 0, 0, (const char[]){ 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { 218, 9, 11, 0, 0, 0, 0, (const char[]){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x0F, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00 } }, + { 219, 8, 11, 0, 0, 0, 0, (const char[]){ 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F } }, + { 220, 8, 11, 0, 0, 0, 0, (const char[]){ 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F } }, + { 221, 4, 11, 0, 0, 0, 0, (const char[]){ 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F } }, + { 222, 8, 11, 0, 0, 0, 0, (const char[]){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F } }, + { 223, 8, 11, 0, 0, 0, 0, (const char[]){ 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00 } }, + { 224, 8, 11, 0, 0, 0, 0, (const char[]){ 0xF0, 0x00, 0xF8, 0x01, 0x08, 0x01, 0x08, 0x01, 0xF8, 0x01, 0xF0, 0x00, 0x98, 0x01, 0x98, 0x01 } }, + { 225, 8, 11, 0, 0, 0, 0, (const char[]){ 0x00, 0x02, 0xFE, 0x03, 0xFE, 0x01, 0x92, 0x00, 0x12, 0x01, 0x3E, 0x01, 0xEC, 0x01, 0xC0, 0x00 } }, + { 226, 8, 11, 0, 0, 0, 0, (const char[]){ 0x08, 0x01, 0xF8, 0x01, 0xF8, 0x01, 0x08, 0x01, 0x08, 0x00, 0x08, 0x00, 0x18, 0x00, 0x18, 0x00 } }, + { 227, 8, 11, 0, 0, 0, 0, (const char[]){ 0x08, 0x01, 0xF8, 0x01, 0xF8, 0x01, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x01, 0xF8, 0x01, 0x08, 0x01 } }, + { 228, 7, 11, 0, 0, 0, 0, (const char[]){ 0x86, 0x01, 0xCE, 0x01, 0x7A, 0x01, 0x32, 0x01, 0x02, 0x01, 0x86, 0x01, 0x86, 0x01 } }, + { 229, 7, 11, 0, 0, 0, 0, (const char[]){ 0xF0, 0x00, 0xF8, 0x01, 0x08, 0x01, 0x08, 0x01, 0xF8, 0x01, 0xF8, 0x00, 0x18, 0x00 } }, + { 230, 8, 11, 0, 0, 0, 0, (const char[]){ 0x08, 0x00, 0xF8, 0x07, 0xF8, 0x07, 0x00, 0x01, 0x00, 0x01, 0xF8, 0x00, 0xF8, 0x01, 0x08, 0x01 } }, + { 231, 7, 11, 0, 0, 0, 0, (const char[]){ 0x02, 0x00, 0x02, 0x00, 0xFE, 0x00, 0xFE, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01 } }, + { 232, 8, 11, 0, 0, 0, 0, (const char[]){ 0x30, 0x00, 0x78, 0x00, 0x4A, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0x4A, 0x01, 0x78, 0x00, 0x30, 0x00 } }, + { 233, 9, 11, 0, 0, 0, 0, (const char[]){ 0xFC, 0x00, 0x02, 0x01, 0x7A, 0x01, 0x7A, 0x01, 0x22, 0x01, 0x7A, 0x01, 0x7A, 0x01, 0x02, 0x01, 0xFC, 0x00 } }, + { 234, 8, 11, 0, 0, 0, 0, (const char[]){ 0x7C, 0x01, 0xFE, 0x01, 0x82, 0x01, 0x02, 0x00, 0x02, 0x00, 0x82, 0x01, 0xFE, 0x01, 0x7C, 0x01 } }, + { 235, 6, 11, 0, 0, 0, 0, (const char[]){ 0xF6, 0x00, 0xFE, 0x01, 0x0A, 0x01, 0x0A, 0x01, 0xFA, 0x01, 0xFA, 0x00 } }, + { 236, 8, 11, 0, 0, 0, 0, (const char[]){ 0xF0, 0x00, 0xF8, 0x01, 0x08, 0x01, 0xF8, 0x01, 0xF8, 0x01, 0x08, 0x01, 0xF8, 0x01, 0xF0, 0x00 } }, + { 237, 8, 11, 0, 0, 0, 0, (const char[]){ 0xF0, 0x00, 0xF0, 0x01, 0x00, 0x01, 0xFC, 0x07, 0xFE, 0x07, 0x02, 0x01, 0xFE, 0x01, 0xFC, 0x00 } }, + { 238, 7, 11, 0, 0, 0, 0, (const char[]){ 0x90, 0x00, 0x98, 0x01, 0x68, 0x01, 0x68, 0x01, 0x08, 0x01, 0x98, 0x01, 0x90, 0x00 } }, + { 239, 7, 11, 0, 0, 0, 0, (const char[]){ 0xFC, 0x01, 0xFE, 0x01, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0xFE, 0x01, 0xFC, 0x01 } }, + { 240, 6, 11, 0, 0, 0, 0, (const char[]){ 0xA8, 0x00, 0xA8, 0x00, 0xA8, 0x00, 0xA8, 0x00, 0xA8, 0x00, 0xA8, 0x00 } }, + { 241, 6, 11, 0, 0, 0, 0, (const char[]){ 0x10, 0x01, 0x10, 0x01, 0x7C, 0x01, 0x7C, 0x01, 0x10, 0x01, 0x10, 0x01 } }, + { 242, 5, 11, 0, 0, 0, 0, (const char[]){ 0x82, 0x02, 0xC6, 0x02, 0x6C, 0x02, 0x38, 0x02, 0x10, 0x02 } }, + { 243, 5, 11, 0, 0, 0, 0, (const char[]){ 0x10, 0x02, 0x38, 0x02, 0x6C, 0x02, 0xC6, 0x02, 0x82, 0x02 } }, + { 244, 8, 11, 0, 0, 0, 2, (const char[]){ 0x00, 0x00, 0x00, 0x00, 0xFC, 0x0F, 0xFE, 0x0F, 0x03, 0x00, 0x03, 0x00, 0x06, 0x00, 0x04, 0x00 } }, + { 245, 4, 11, 0, 0, 0, 0, (const char[]){ 0x00, 0x06, 0x00, 0x06, 0xFF, 0x07, 0xFF, 0x03 } }, + { 246, 6, 11, 0, 0, 0, 0, (const char[]){ 0x20, 0x00, 0x20, 0x00, 0xAC, 0x01, 0xAC, 0x01, 0x20, 0x00, 0x20, 0x00 } }, + { 247, 5, 11, 0, 0, 0, 0, (const char[]){ 0x90, 0x00, 0x48, 0x00, 0x90, 0x00, 0x20, 0x01, 0x90, 0x00 } }, + { 248, 5, 11, 0, 0, 0, 0, (const char[]){ 0x0E, 0x00, 0x1F, 0x00, 0x11, 0x00, 0x1F, 0x00, 0x0E, 0x00 } }, + { 249, 5, 11, 0, 0, 0, 0, (const char[]){ 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00 } }, + { 250, 7, 11, 0, 0, 0, 0, (const char[]){ 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x78, 0x00, 0x78, 0x00, 0x30, 0x00, 0x00, 0x00 } }, + { 251, 9, 11, 0, 2, 0, 3, (const char[]){ 0x02, 0x00, 0xFE, 0x03, 0xFE, 0x00, 0x30, 0x00, 0x0C, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00 } }, + { 252, 6, 11, 0, 0, 1, 1, (const char[]){ 0x02, 0x00, 0x1E, 0x00, 0x1F, 0x00, 0x01, 0x00, 0x1F, 0x00, 0x1E, 0x00 } }, + { 253, 6, 11, 0, 0, 1, 1, (const char[]){ 0x12, 0x00, 0x1B, 0x00, 0x19, 0x00, 0x15, 0x00, 0x17, 0x00, 0x12, 0x00 } }, + { 254, 7, 11, 0, 0, 0, 0, (const char[]){ 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0x00, 0x00 } }, + { 255, 6, 11, 0, 0, 0, 0, (const char[]){ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } +}; +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Doggy/xfont_8.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,231 @@ +#ifndef XFONT_8_H +#define XFONT_8_H + +const XGlyph xfont_8[] = { + { 0, 5, 8, 0, 0, 0, 0, (const char[]){ 0xFF, 0x81, 0x81, 0x81, 0xFF } }, + { 32, 2, 8, 0, 0, 0, 0, (const char[]){ 0x00, 0x00 } }, + { 33, 1, 8, 0, 0, 0, 0, (const char[]){ 0x2F } }, // ! + { 34, 3, 8, 0, 0, 1, 1, (const char[]){ 0x03, 0x00, 0x03 } }, // " + { 35, 5, 8, 0, 0, 0, 0, (const char[]){ 0x14, 0x3E, 0x14, 0x3E, 0x14 } }, // # + { 36, 5, 8, 0, 0, 0, 0, (const char[]){ 0x24, 0x6A, 0x3E, 0x2B, 0x12 } }, // $ + { 37, 5, 8, 0, 0, 0, 0, (const char[]){ 0x22, 0x10, 0x08, 0x04, 0x22 } }, // % + { 38, 5, 8, 0, 0, 0, 0, (const char[]){ 0x14, 0x2A, 0x2A, 0x14, 0x20 } }, // & + { 39, 1, 8, 0, 0, 1, 1, (const char[]){ 0x03 } }, // ' + { 40, 2, 8, 0, 0, 0, 0, (const char[]){ 0x1E, 0x21 } }, // ( + { 41, 2, 8, 0, 0, 0, 0, (const char[]){ 0x21, 0x1E } }, // ) + { 42, 5, 8, 0, 0, 0, 0, (const char[]){ 0x14, 0x08, 0x3E, 0x08, 0x14 } }, // * + { 43, 5, 8, 0, 0, 0, 0, (const char[]){ 0x08, 0x08, 0x3E, 0x08, 0x08 } }, // + + { 44, 4, 8, 2, 0, 1, 0, (const char[]){ 0x00, 0x80, 0x70, 0x30 } }, // , + { 45, 5, 8, 0, 0, 0, 0, (const char[]){ 0x08, 0x08, 0x08, 0x08, 0x08 } }, // - + { 46, 5, 8, 2, 0, 0, 0, (const char[]){ 0x00, 0x00, 0x30, 0x30, 0x00 } }, // . + { 47, 5, 8, 0, 0, 0, 0, (const char[]){ 0x20, 0x10, 0x08, 0x04, 0x02 } }, // / + { 48, 5, 8, 0, 0, 0, 0, (const char[]){ 0x1E, 0x31, 0x2D, 0x23, 0x1E } }, // 0 + { 49, 5, 8, 0, 0, 0, 0, (const char[]){ 0x00, 0x00, 0x02, 0x3F, 0x00 } }, // 1 + { 50, 5, 8, 0, 0, 0, 0, (const char[]){ 0x22, 0x31, 0x29, 0x25, 0x22 } }, // 2 + { 51, 5, 8, 0, 0, 0, 0, (const char[]){ 0x12, 0x21, 0x25, 0x25, 0x1A } }, // 3 + { 52, 5, 8, 0, 0, 0, 0, (const char[]){ 0x18, 0x14, 0x12, 0x3F, 0x10 } }, // 4 + { 53, 5, 8, 0, 0, 0, 0, (const char[]){ 0x17, 0x25, 0x25, 0x25, 0x19 } }, // 5 + { 54, 5, 8, 0, 0, 0, 0, (const char[]){ 0x1E, 0x25, 0x25, 0x25, 0x18 } }, // 6 + { 55, 5, 8, 0, 0, 0, 0, (const char[]){ 0x01, 0x01, 0x39, 0x05, 0x03 } }, // 7 + { 56, 5, 8, 0, 0, 0, 0, (const char[]){ 0x1A, 0x25, 0x25, 0x25, 0x1A } }, // 8 + { 57, 5, 8, 0, 0, 0, 0, (const char[]){ 0x06, 0x29, 0x29, 0x29, 0x1E } }, // 9 + { 58, 4, 8, 2, 0, 2, 0, (const char[]){ 0x00, 0x00, 0x36, 0x36 } }, // : + { 59, 4, 8, 2, 0, 1, 0, (const char[]){ 0x00, 0x80, 0x76, 0x36 } }, // ; + { 60, 6, 8, 0, 0, 0, 0, (const char[]){ 0x08, 0x08, 0x14, 0x14, 0x22, 0x22 } }, // < + { 61, 5, 8, 0, 0, 0, 0, (const char[]){ 0x14, 0x14, 0x14, 0x14, 0x14 } }, // = + { 62, 6, 8, 0, 0, 0, 0, (const char[]){ 0x22, 0x22, 0x14, 0x14, 0x08, 0x08 } }, // > + { 63, 5, 8, 0, 0, 0, 0, (const char[]){ 0x02, 0x01, 0x29, 0x05, 0x02 } }, // ? + { 64, 6, 8, 0, 0, 0, 0, (const char[]){ 0x3E, 0x41, 0x5D, 0x55, 0x5E, 0x20 } }, // @ + { 65, 5, 8, 0, 0, 0, 0, (const char[]){ 0x3E, 0x09, 0x09, 0x09, 0x3E } }, // + { 66, 5, 8, 0, 0, 0, 0, (const char[]){ 0x3F, 0x25, 0x25, 0x25, 0x1A } }, // + { 67, 5, 8, 0, 0, 0, 0, (const char[]){ 0x1E, 0x21, 0x21, 0x21, 0x12 } }, // + { 68, 5, 8, 0, 0, 0, 0, (const char[]){ 0x3F, 0x21, 0x21, 0x22, 0x1C } }, // + { 69, 5, 8, 0, 0, 0, 0, (const char[]){ 0x3F, 0x25, 0x25, 0x25, 0x21 } }, // + { 70, 5, 8, 0, 0, 0, 2, (const char[]){ 0x3F, 0x05, 0x05, 0x05, 0x01 } }, // + { 71, 5, 8, 0, 0, 0, 0, (const char[]){ 0x1E, 0x21, 0x21, 0x29, 0x1A } }, // + { 72, 5, 8, 0, 0, 0, 0, (const char[]){ 0x3F, 0x04, 0x04, 0x04, 0x3F } }, // + { 73, 3, 8, 0, 0, 0, 0, (const char[]){ 0x21, 0x3F, 0x21 } }, // I + { 74, 5, 8, 1, 0, 0, 0, (const char[]){ 0x18, 0x20, 0x21, 0x1F, 0x01 } }, // + { 75, 5, 8, 0, 0, 0, 0, (const char[]){ 0x3F, 0x04, 0x04, 0x0A, 0x31 } }, // + { 76, 5, 8, 0, 1, 0, 0, (const char[]){ 0x3F, 0x20, 0x20, 0x20, 0x20 } }, // + { 77, 5, 8, 0, 0, 0, 0, (const char[]){ 0x3F, 0x02, 0x04, 0x02, 0x3F } }, // + { 78, 5, 8, 0, 0, 0, 0, (const char[]){ 0x3F, 0x02, 0x04, 0x08, 0x3F } }, // + { 79, 5, 8, 0, 0, 0, 0, (const char[]){ 0x1E, 0x21, 0x21, 0x21, 0x1E } }, // + { 80, 5, 8, 0, 0, 0, 1, (const char[]){ 0x3F, 0x09, 0x09, 0x09, 0x06 } }, // + { 81, 5, 8, 0, 0, 0, 0, (const char[]){ 0x1E, 0x21, 0x29, 0x31, 0x3E } }, // + { 82, 5, 8, 0, 0, 0, 0, (const char[]){ 0x3F, 0x09, 0x09, 0x19, 0x26 } }, // + { 83, 5, 8, 0, 0, 0, 0, (const char[]){ 0x12, 0x25, 0x25, 0x25, 0x1A } }, // + { 84, 5, 8, 0, 0, 2, 2, (const char[]){ 0x01, 0x01, 0x3F, 0x01, 0x01 } }, // + { 85, 5, 8, 0, 0, 0, 0, (const char[]){ 0x1F, 0x20, 0x20, 0x20, 0x1F } }, // + { 86, 5, 8, 0, 0, 0, 0, (const char[]){ 0x03, 0x0C, 0x30, 0x0C, 0x03 } }, // + { 87, 5, 8, 0, 0, 0, 0, (const char[]){ 0x1F, 0x20, 0x18, 0x20, 0x1F } }, // + { 88, 5, 8, 0, 0, 0, 0, (const char[]){ 0x21, 0x12, 0x0C, 0x12, 0x21 } }, // + { 89, 5, 8, 0, 0, 1, 1, (const char[]){ 0x03, 0x04, 0x38, 0x04, 0x03 } }, // + { 90, 5, 8, 0, 0, 0, 0, (const char[]){ 0x31, 0x29, 0x25, 0x23, 0x21 } }, // + { 91, 4, 8, 1, 0, 1, 0, (const char[]){ 0x00, 0x3F, 0x21, 0x21 } }, // + { 92, 5, 8, 0, 0, 1, 0, (const char[]){ 0x02, 0x04, 0x08, 0x10, 0x20 } }, // + { 93, 5, 8, 2, 0, 2, 0, (const char[]){ 0x00, 0x00, 0x21, 0x21, 0x3F } }, // + { 94, 5, 8, 0, 0, 0, 0, (const char[]){ 0x04, 0x02, 0x01, 0x02, 0x04 } }, // + { 95, 5, 8, 0, 0, 0, 0, (const char[]){ 0x20, 0x20, 0x20, 0x20, 0x20 } }, // + { 96, 4, 8, 1, 0, 2, 0, (const char[]){ 0x00, 0x01, 0x03, 0x04 } }, // + { 97, 4, 8, 1, 0, 0, 0, (const char[]){ 0x10, 0x2A, 0x2A, 0x3C } }, // + { 98, 4, 8, 0, 0, 0, 0, (const char[]){ 0x3F, 0x24, 0x22, 0x1C } }, // + { 99, 4, 8, 0, 0, 0, 0, (const char[]){ 0x1C, 0x22, 0x22, 0x14 } }, // + { 100, 4, 8, 0, 0, 0, 0, (const char[]){ 0x1C, 0x22, 0x24, 0x3F } }, // + { 101, 4, 8, 0, 0, 0, 0, (const char[]){ 0x1C, 0x2A, 0x2A, 0x2C } }, // + { 102, 4, 8, 0, 0, 0, 1, (const char[]){ 0x3E, 0x09, 0x01, 0x02 } }, // + { 103, 4, 8, 0, 0, 0, 0, (const char[]){ 0x0C, 0x52, 0x4A, 0x3C } }, // + { 104, 4, 8, 0, 0, 1, 0, (const char[]){ 0x3F, 0x04, 0x02, 0x3C } }, // + { 105, 1, 8, 0, 0, 0, 0, (const char[]){ 0x3D } }, // i + { 106, 3, 8, 1, 0, 0, 0, (const char[]){ 0x40, 0x40, 0x3D } }, // + { 107, 4, 8, 0, 0, 0, 0, (const char[]){ 0x3F, 0x08, 0x0C, 0x32 } }, // + { 108, 1, 8, 0, 0, 0, 0, (const char[]){ 0x3F } }, // l + { 109, 5, 8, 0, 0, 0, 0, (const char[]){ 0x3C, 0x02, 0x3C, 0x02, 0x3C } }, // + { 110, 4, 8, 0, 0, 0, 0, (const char[]){ 0x3C, 0x02, 0x02, 0x3C } }, // + { 111, 4, 8, 1, 1, 0, 0, (const char[]){ 0x1C, 0x22, 0x22, 0x1C } }, // + { 112, 4, 8, 0, 0, 0, 0, (const char[]){ 0x7E, 0x22, 0x22, 0x1C } }, // + { 113, 4, 8, 0, 0, 0, 0, (const char[]){ 0x1C, 0x22, 0x22, 0x7E } }, // + { 114, 4, 8, 0, 0, 0, 1, (const char[]){ 0x02, 0x3C, 0x02, 0x02 } }, // + { 115, 4, 8, 0, 0, 0, 0, (const char[]){ 0x24, 0x2A, 0x2A, 0x12 } }, // + { 116, 4, 8, 0, 0, 1, 0, (const char[]){ 0x02, 0x1F, 0x22, 0x22 } }, // + { 117, 4, 8, 0, 0, 0, 0, (const char[]){ 0x1E, 0x20, 0x20, 0x3E } }, // + { 118, 5, 8, 0, 0, 0, 0, (const char[]){ 0x06, 0x18, 0x20, 0x3C, 0x02 } }, // + { 119, 5, 8, 0, 0, 0, 0, (const char[]){ 0x1E, 0x20, 0x1C, 0x20, 0x1E } }, // + { 120, 5, 8, 0, 0, 0, 0, (const char[]){ 0x22, 0x14, 0x08, 0x14, 0x22 } }, // + { 121, 4, 8, 0, 0, 0, 0, (const char[]){ 0x0E, 0x50, 0x50, 0x3E } }, // + { 122, 4, 8, 0, 0, 0, 0, (const char[]){ 0x22, 0x32, 0x2A, 0x26 } }, // + { 123, 4, 8, 1, 0, 1, 0, (const char[]){ 0x00, 0x08, 0x36, 0x41 } }, // + { 124, 3, 8, 2, 0, 2, 0, (const char[]){ 0x00, 0x00, 0x7F } }, // + { 125, 4, 8, 1, 0, 1, 0, (const char[]){ 0x00, 0x41, 0x36, 0x08 } }, // + { 126, 5, 8, 0, 0, 0, 0, (const char[]){ 0x08, 0x04, 0x08, 0x10, 0x08 } }, // + { 127, 4, 8, 0, 1, 0, 1, (const char[]){ 0x2A, 0x55, 0x2A, 0x55 } }, // + { 128, 5, 8, 0, 0, 0, 0, (const char[]){ 0x1E, 0xA1, 0x61, 0x21, 0x12 } }, // + { 129, 4, 8, 0, 0, 0, 0, (const char[]){ 0x1D, 0x20, 0x20, 0x3D } }, // + { 130, 4, 8, 0, 0, 0, 0, (const char[]){ 0x1C, 0x2A, 0x2B, 0x2D } }, // + { 131, 4, 8, 0, 0, 0, 0, (const char[]){ 0x11, 0x2B, 0x2B, 0x3D } }, // + { 132, 4, 8, 0, 0, 0, 0, (const char[]){ 0x11, 0x2A, 0x2A, 0x3D } }, // + { 133, 4, 8, 0, 0, 0, 0, (const char[]){ 0x11, 0x2B, 0x2A, 0x3C } }, // + { 134, 4, 8, 0, 0, 0, 0, (const char[]){ 0x10, 0x2A, 0x2B, 0x3C } }, // + { 135, 4, 8, 0, 0, 0, 0, (const char[]){ 0x1C, 0xA2, 0x62, 0x14 } }, // + { 136, 4, 8, 0, 0, 0, 0, (const char[]){ 0x1D, 0x2B, 0x2B, 0x2D } }, // + { 137, 4, 8, 0, 0, 0, 0, (const char[]){ 0x1D, 0x2A, 0x2A, 0x2D } }, // + { 138, 4, 8, 0, 0, 0, 0, (const char[]){ 0x1D, 0x2B, 0x2A, 0x2C } }, // + { 139, 3, 8, 0, 0, 1, 1, (const char[]){ 0x01, 0x3C, 0x01 } }, // + { 140, 5, 8, 0, 0, 1, 1, (const char[]){ 0x02, 0x01, 0x3D, 0x01, 0x02 } }, // + { 141, 3, 8, 0, 0, 1, 1, (const char[]){ 0x01, 0x3D, 0x02 } }, // + { 142, 5, 8, 0, 0, 0, 0, (const char[]){ 0x3C, 0x13, 0x12, 0x13, 0x3C } }, // + { 143, 5, 8, 0, 0, 0, 0, (const char[]){ 0x3C, 0x12, 0x13, 0x12, 0x3C } }, // + { 144, 5, 8, 0, 0, 0, 0, (const char[]){ 0x3E, 0x2A, 0x2A, 0x2B, 0x23 } }, // + { 145, 6, 8, 0, 0, 0, 0, (const char[]){ 0x10, 0x2A, 0x2A, 0x3C, 0x2A, 0x2C } }, // + { 146, 6, 8, 0, 0, 0, 0, (const char[]){ 0x3E, 0x11, 0x11, 0x3F, 0x25, 0x25 } }, // + { 147, 4, 8, 0, 0, 0, 0, (const char[]){ 0x1D, 0x23, 0x23, 0x1D } }, // + { 148, 4, 8, 0, 0, 0, 0, (const char[]){ 0x1D, 0x22, 0x22, 0x1D } }, // + { 149, 4, 8, 0, 0, 0, 0, (const char[]){ 0x1D, 0x23, 0x22, 0x1C } }, // + { 150, 4, 8, 0, 0, 0, 0, (const char[]){ 0x1D, 0x21, 0x21, 0x3D } }, // + { 151, 4, 8, 0, 0, 0, 0, (const char[]){ 0x1D, 0x21, 0x22, 0x3C } }, // + { 152, 4, 8, 0, 0, 0, 0, (const char[]){ 0x0D, 0x50, 0x50, 0x3D } }, // + { 153, 5, 8, 0, 0, 0, 0, (const char[]){ 0x1C, 0x23, 0x22, 0x23, 0x1C } }, // + { 154, 5, 8, 0, 0, 0, 0, (const char[]){ 0x1E, 0x21, 0x20, 0x21, 0x1E } }, // + { 155, 5, 8, 0, 0, 0, 0, (const char[]){ 0x1C, 0x22, 0x63, 0x22, 0x14 } }, // + { 156, 5, 8, 0, 0, 0, 0, (const char[]){ 0x26, 0x39, 0x29, 0x21, 0x22 } }, // + { 157, 5, 8, 0, 0, 0, 0, (const char[]){ 0x0A, 0x0F, 0x3A, 0x0F, 0x0A } }, // + { 158, 6, 8, 0, 0, 0, 0, (const char[]){ 0x14, 0x3E, 0x55, 0x55, 0x41, 0x22 } }, // + { 159, 5, 8, 0, 0, 0, 1, (const char[]){ 0x48, 0x3E, 0x09, 0x01, 0x02 } }, // + { 160, 4, 8, 0, 0, 0, 0, (const char[]){ 0x10, 0x2A, 0x2B, 0x3D } }, // + { 161, 4, 8, 1, 0, 2, 1, (const char[]){ 0x00, 0x02, 0x3D, 0x01 } }, // + { 162, 4, 8, 0, 0, 0, 0, (const char[]){ 0x1C, 0x22, 0x23, 0x1D } }, // + { 163, 4, 8, 0, 0, 0, 0, (const char[]){ 0x1C, 0x22, 0x21, 0x3C } }, // + { 164, 5, 8, 0, 0, 0, 0, (const char[]){ 0x0A, 0x39, 0x05, 0x06, 0x3A } }, // + { 165, 5, 8, 0, 0, 0, 0, (const char[]){ 0x3E, 0x05, 0x09, 0x12, 0x3F } }, // + { 166, 5, 8, 1, 0, 2, 1, (const char[]){ 0x00, 0x05, 0x0B, 0x09, 0x0E } }, // + { 167, 5, 8, 1, 0, 2, 1, (const char[]){ 0x00, 0x06, 0x09, 0x09, 0x06 } }, // + { 168, 5, 8, 1, 1, 0, 0, (const char[]){ 0x20, 0x50, 0x4A, 0x40, 0x20 } }, // + { 169, 5, 8, 1, 0, 1, 0, (const char[]){ 0x00, 0x38, 0x08, 0x08, 0x08 } }, // + { 170, 5, 8, 1, 0, 1, 0, (const char[]){ 0x00, 0x08, 0x08, 0x08, 0x38 } }, // + { 171, 5, 8, 0, 0, 0, 0, (const char[]){ 0x11, 0x0F, 0x4C, 0x6A, 0x51 } }, // + { 172, 5, 8, 0, 0, 0, 0, (const char[]){ 0x11, 0x0F, 0x3C, 0x22, 0x71 } }, // + { 173, 3, 8, 2, 0, 2, 0, (const char[]){ 0x00, 0x00, 0x3D } }, // + { 174, 6, 8, 0, 0, 0, 0, (const char[]){ 0x08, 0x14, 0x22, 0x08, 0x14, 0x22 } }, // + { 175, 6, 8, 0, 0, 0, 0, (const char[]){ 0x22, 0x14, 0x08, 0x22, 0x14, 0x08 } }, // + { 176, 4, 8, 0, 1, 0, 1, (const char[]){ 0x55, 0x00, 0x55, 0x00 } }, // + { 177, 4, 8, 0, 1, 0, 1, (const char[]){ 0x55, 0xAA, 0x55, 0xAA } }, // + { 178, 4, 8, 0, 1, 0, 1, (const char[]){ 0xFF, 0xAA, 0xFF, 0xAA } }, // + { 179, 7, 8, 0, 1, 0, 1, (const char[]){ 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00 } }, // + { 180, 7, 8, 0, 1, 0, 1, (const char[]){ 0x08, 0x08, 0x08, 0xFF, 0x00, 0x00, 0x00 } }, // + { 181, 7, 8, 0, 1, 0, 1, (const char[]){ 0x14, 0x14, 0x14, 0xFF, 0x00, 0x00, 0x00 } }, // + { 182, 7, 8, 0, 1, 0, 1, (const char[]){ 0x08, 0x08, 0xFF, 0x00, 0xFF, 0x00, 0x00 } }, // + { 183, 7, 8, 0, 1, 0, 1, (const char[]){ 0x08, 0x08, 0xF8, 0x08, 0xF8, 0x00, 0x00 } }, // + { 184, 7, 8, 0, 1, 0, 1, (const char[]){ 0x14, 0x14, 0x14, 0xFC, 0x00, 0x00, 0x00 } }, // + { 185, 7, 8, 0, 1, 0, 1, (const char[]){ 0x14, 0x14, 0xF7, 0x00, 0xFF, 0x00, 0x00 } }, // + { 186, 7, 8, 0, 1, 0, 1, (const char[]){ 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00 } }, // + { 187, 7, 8, 0, 1, 0, 1, (const char[]){ 0x14, 0x14, 0xF4, 0x04, 0xFC, 0x00, 0x00 } }, // + { 188, 7, 8, 0, 1, 0, 1, (const char[]){ 0x14, 0x14, 0x17, 0x10, 0x1F, 0x00, 0x00 } }, // + { 189, 7, 8, 0, 1, 0, 1, (const char[]){ 0x08, 0x08, 0x0F, 0x08, 0x0F, 0x00, 0x00 } }, // + { 190, 7, 8, 0, 1, 0, 1, (const char[]){ 0x14, 0x14, 0x14, 0x1F, 0x00, 0x00, 0x00 } }, // + { 191, 7, 8, 0, 1, 0, 1, (const char[]){ 0x08, 0x08, 0x08, 0xF8, 0x00, 0x00, 0x00 } }, // + { 192, 7, 8, 0, 1, 0, 1, (const char[]){ 0x00, 0x00, 0x00, 0x0F, 0x08, 0x08, 0x08 } }, // + { 193, 7, 8, 0, 1, 0, 1, (const char[]){ 0x08, 0x08, 0x08, 0x0F, 0x08, 0x08, 0x08 } }, // + { 194, 7, 8, 0, 1, 0, 1, (const char[]){ 0x08, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x08 } }, // + { 195, 7, 8, 0, 1, 0, 1, (const char[]){ 0x00, 0x00, 0x00, 0xFF, 0x08, 0x08, 0x08 } }, // + { 196, 7, 8, 0, 1, 0, 1, (const char[]){ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 } }, // + { 197, 7, 8, 0, 1, 0, 1, (const char[]){ 0x08, 0x08, 0x08, 0xFF, 0x08, 0x08, 0x08 } }, // + { 198, 7, 8, 0, 1, 0, 1, (const char[]){ 0x00, 0x00, 0x00, 0xFF, 0x14, 0x14, 0x14 } }, // + { 199, 7, 8, 0, 1, 0, 1, (const char[]){ 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x08, 0x08 } }, // + { 200, 7, 8, 0, 1, 0, 1, (const char[]){ 0x00, 0x00, 0x1F, 0x10, 0x17, 0x14, 0x14 } }, // + { 201, 7, 8, 0, 1, 0, 1, (const char[]){ 0x00, 0x00, 0xFC, 0x04, 0xF4, 0x14, 0x14 } }, // + { 202, 7, 8, 0, 1, 0, 1, (const char[]){ 0x14, 0x14, 0x17, 0x10, 0x17, 0x14, 0x14 } }, // + { 203, 7, 8, 0, 1, 0, 1, (const char[]){ 0x14, 0x14, 0xF4, 0x04, 0xF4, 0x14, 0x14 } }, // + { 204, 7, 8, 0, 1, 0, 1, (const char[]){ 0x00, 0x00, 0xFF, 0x00, 0xF7, 0x14, 0x14 } }, // + { 205, 7, 8, 0, 1, 0, 1, (const char[]){ 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14 } }, // + { 206, 7, 8, 0, 1, 0, 1, (const char[]){ 0x14, 0x14, 0xF7, 0x00, 0xF7, 0x14, 0x14 } }, // + { 207, 7, 8, 0, 1, 0, 1, (const char[]){ 0x14, 0x14, 0x14, 0x17, 0x14, 0x14, 0x14 } }, // + { 208, 7, 8, 0, 1, 0, 1, (const char[]){ 0x08, 0x08, 0x0F, 0x08, 0x0F, 0x08, 0x08 } }, // + { 209, 7, 8, 0, 1, 0, 1, (const char[]){ 0x14, 0x14, 0x14, 0xF4, 0x14, 0x14, 0x14 } }, // + { 210, 7, 8, 0, 1, 0, 1, (const char[]){ 0x08, 0x08, 0xF8, 0x08, 0xF8, 0x08, 0x08 } }, // + { 211, 7, 8, 0, 1, 0, 1, (const char[]){ 0x00, 0x00, 0x0F, 0x08, 0x0F, 0x08, 0x08 } }, // + { 212, 7, 8, 0, 1, 0, 1, (const char[]){ 0x00, 0x00, 0x00, 0x1F, 0x14, 0x14, 0x14 } }, // + { 213, 7, 8, 0, 1, 0, 1, (const char[]){ 0x00, 0x00, 0x00, 0xFC, 0x14, 0x14, 0x14 } }, // + { 214, 7, 8, 0, 1, 0, 1, (const char[]){ 0x00, 0x00, 0xF8, 0x08, 0xF8, 0x08, 0x08 } }, // + { 215, 7, 8, 0, 1, 0, 1, (const char[]){ 0x08, 0x08, 0xFF, 0x08, 0xFF, 0x08, 0x08 } }, // + { 216, 7, 8, 0, 1, 0, 1, (const char[]){ 0x14, 0x14, 0x14, 0xFF, 0x14, 0x14, 0x14 } }, // + { 217, 7, 8, 0, 1, 0, 1, (const char[]){ 0x08, 0x08, 0x08, 0x0F, 0x00, 0x00, 0x00 } }, // + { 218, 7, 8, 0, 1, 0, 1, (const char[]){ 0x00, 0x00, 0x00, 0xF8, 0x08, 0x08, 0x08 } }, // + { 219, 7, 8, 0, 1, 0, 1, (const char[]){ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } }, // + { 220, 7, 8, 0, 1, 0, 1, (const char[]){ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0 } }, // + { 221, 7, 8, 0, 1, 0, 1, (const char[]){ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00 } }, // + { 222, 7, 8, 0, 1, 0, 1, (const char[]){ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF } }, // + { 223, 7, 8, 0, 1, 0, 1, (const char[]){ 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F } }, // + { 224, 6, 8, 0, 0, 0, 0, (const char[]){ 0x18, 0x24, 0x24, 0x18, 0x24, 0x24 } }, // + { 225, 6, 8, 1, 0, 0, 0, (const char[]){ 0x40, 0x3E, 0x2A, 0x4A, 0x4C, 0x30 } }, // + { 226, 6, 8, 0, 0, 0, 0, (const char[]){ 0x22, 0x3E, 0x22, 0x02, 0x02, 0x06 } }, // + { 227, 6, 8, 0, 0, 0, 0, (const char[]){ 0x22, 0x3E, 0x02, 0x02, 0x3E, 0x22 } }, // + { 228, 6, 8, 0, 0, 0, 0, (const char[]){ 0x33, 0x2D, 0x21, 0x21, 0x21, 0x33 } }, // + { 229, 6, 8, 0, 0, 0, 0, (const char[]){ 0x18, 0x24, 0x24, 0x24, 0x1C, 0x04 } }, // + { 230, 6, 8, 0, 0, 0, 0, (const char[]){ 0x04, 0x7C, 0x20, 0x20, 0x1C, 0x24 } }, // + { 231, 6, 8, 1, 0, 1, 0, (const char[]){ 0x00, 0x02, 0x02, 0x1E, 0x22, 0x22 } }, // + { 232, 7, 8, 0, 0, 0, 0, (const char[]){ 0x08, 0x14, 0x55, 0x7F, 0x55, 0x14, 0x08 } }, // + { 233, 7, 8, 0, 0, 0, 0, (const char[]){ 0x3E, 0x41, 0x5D, 0x49, 0x5D, 0x41, 0x3E } }, // + { 234, 6, 8, 0, 0, 0, 0, (const char[]){ 0x2E, 0x31, 0x01, 0x01, 0x31, 0x2E } }, // + { 235, 6, 8, 0, 0, 0, 0, (const char[]){ 0x00, 0x1B, 0x25, 0x25, 0x25, 0x18 } }, // + { 236, 7, 8, 0, 0, 0, 0, (const char[]){ 0x18, 0x24, 0x24, 0x18, 0x24, 0x24, 0x18 } }, // + { 237, 6, 8, 0, 0, 0, 0, (const char[]){ 0x00, 0x1C, 0x20, 0x7C, 0x22, 0x1C } }, // + { 238, 6, 8, 0, 0, 0, 0, (const char[]){ 0x14, 0x2A, 0x2A, 0x2A, 0x22, 0x16 } }, // + { 239, 5, 8, 0, 0, 0, 0, (const char[]){ 0x3C, 0x02, 0x02, 0x02, 0x3C } }, // + { 240, 5, 8, 0, 0, 0, 0, (const char[]){ 0x2A, 0x2A, 0x2A, 0x2A, 0x2A } }, // + { 241, 5, 8, 0, 0, 0, 0, (const char[]){ 0x44, 0x44, 0x5F, 0x44, 0x44 } }, // + { 242, 6, 8, 0, 0, 0, 0, (const char[]){ 0x51, 0x51, 0x4A, 0x4A, 0x44, 0x44 } }, // + { 243, 6, 8, 0, 0, 0, 0, (const char[]){ 0x44, 0x44, 0x4A, 0x4A, 0x51, 0x51 } }, // + { 244, 5, 8, 2, 0, 2, 0, (const char[]){ 0x00, 0x00, 0xFE, 0x01, 0x02 } }, // + { 245, 3, 8, 0, 0, 0, 0, (const char[]){ 0x20, 0x40, 0x3F } }, // + { 246, 5, 8, 0, 0, 0, 0, (const char[]){ 0x08, 0x08, 0x2A, 0x08, 0x08 } }, // + { 247, 5, 8, 0, 0, 0, 0, (const char[]){ 0x24, 0x12, 0x24, 0x48, 0x24 } }, // + { 248, 5, 8, 0, 0, 1, 1, (const char[]){ 0x00, 0x06, 0x09, 0x09, 0x06 } }, // + { 249, 4, 8, 2, 0, 2, 0, (const char[]){ 0x00, 0x00, 0x00, 0x08 } }, // + { 250, 5, 8, 2, 0, 2, 0, (const char[]){ 0x00, 0x00, 0x08, 0x1C, 0x08 } }, // + { 251, 6, 8, 0, 0, 0, 2, (const char[]){ 0x02, 0x7E, 0x30, 0x0C, 0x02, 0x02 } }, // + { 252, 5, 8, 1, 0, 2, 1, (const char[]){ 0x00, 0x01, 0x0E, 0x01, 0x0E } }, // + { 253, 5, 8, 2, 0, 2, 1, (const char[]){ 0x00, 0x00, 0x09, 0x0D, 0x0A } }, // + { 254, 5, 8, 2, 0, 2, 0, (const char[]){ 0x00, 0x00, 0x1C, 0x1C, 0x1C } }, // + { 255, 5, 8, 0, 0, 0, 0, (const char[]){ 0x00, 0x00, 0x00, 0x00, 0x00 } } +}; +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FatFileSystem/FATDirHandle.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,66 @@ +/* mbed Microcontroller Library - FATDirHandle + * Copyright (c) 2008, sford + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "ff.h" +#include "FATDirHandle.h" +#include "FATFileSystem.h" + +namespace mbed { + +FATDirHandle::FATDirHandle(const FATFS_DIR &the_dir) { + dir = the_dir; +} + +int FATDirHandle::closedir() { + delete this; + return 0; +} + +struct dirent *FATDirHandle::readdir() { + FILINFO finfo; + +#if _USE_LFN + finfo.lfname = cur_entry.d_name; + finfo.lfsize = sizeof(cur_entry.d_name); +#endif // _USE_LFN + + FRESULT res = f_readdir(&dir, &finfo); + +#if _USE_LFN + if(res != 0 || finfo.fname[0]==0) { + return NULL; + } else { + if(cur_entry.d_name[0]==0) { + // No long filename so use short filename. + memcpy(cur_entry.d_name, finfo.fname, sizeof(finfo.fname)); + } + return &cur_entry; + } +#else + if(res != 0 || finfo.fname[0]==0) { + return NULL; + } else { + memcpy(cur_entry.d_name, finfo.fname, sizeof(finfo.fname)); + return &cur_entry; + } +#endif /* _USE_LFN */ +} + +void FATDirHandle::rewinddir() { + dir.index = 0; +} + +off_t FATDirHandle::telldir() { + return dir.index; +} + +void FATDirHandle::seekdir(off_t location) { + dir.index = location; +} + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FatFileSystem/FATDirHandle.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,31 @@ +/* mbed Microcontroller Library - FATDirHandle + * Copyright (c) 2008, sford + */ + +#ifndef MBED_FATDIRHANDLE_H +#define MBED_FATDIRHANDLE_H + +#include "DirHandle.h" +#include "ff.h" + +namespace mbed { + +class FATDirHandle : public DirHandle { + + public: + FATDirHandle(const FATFS_DIR &the_dir); + virtual int closedir(); + virtual struct dirent *readdir(); + virtual void rewinddir(); + virtual off_t telldir(); + virtual void seekdir(off_t location); + + private: + FATFS_DIR dir; + struct dirent cur_entry; + +}; + +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FatFileSystem/FATFileHandle.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,102 @@ +/* mbed Microcontroller Library - FATFileHandle + * Copyright (c) 2008, sford + */ + +#include "FATFileHandle.h" + +#include <stdio.h> +#include <stdlib.h> +#include "ff.h" +#include "FATFileSystem.h" + +namespace mbed { + +#if FFSDEBUG_ENABLED +static const char *FR_ERRORS[] = { + "FR_OK = 0", + "FR_NOT_READY", + "FR_NO_FILE", + "FR_NO_PATH", + "FR_INVALID_NAME", + "FR_INVALID_DRIVE", + "FR_DENIED", + "FR_EXIST", + "FR_RW_ERROR", + "FR_WRITE_PROTECTED", + "FR_NOT_ENABLED", + "FR_NO_FILESYSTEM", + "FR_INVALID_OBJECT", + "FR_MKFS_ABORTED" +}; +#endif + +FATFileHandle::FATFileHandle(FIL fh) { + _fh = fh; +} + +int FATFileHandle::close() { + FFSDEBUG("close\n"); + int retval = f_close(&_fh); + delete this; + return retval; +} + +ssize_t FATFileHandle::write(const void* buffer, size_t length) { + FFSDEBUG("write(%d)\n", length); + UINT n; + FRESULT res = f_write(&_fh, buffer, length, &n); + if(res) { + FFSDEBUG("f_write() failed (%d, %s)", res, FR_ERRORS[res]); + return -1; + } + return n; +} + +ssize_t FATFileHandle::read(void* buffer, size_t length) { + FFSDEBUG("read(%d)\n", length); + UINT n; + FRESULT res = f_read(&_fh, buffer, length, &n); + if(res) { + FFSDEBUG("f_read() failed (%d, %s)\n", res, FR_ERRORS[res]); + return -1; + } + return n; +} + +int FATFileHandle::isatty() { + return 0; +} + +off_t FATFileHandle::lseek(off_t position, int whence) { + FFSDEBUG("lseek(%i,%i)\n",position,whence); + if(whence == SEEK_END) { + position += _fh.fsize; + } else if(whence==SEEK_CUR) { + position += _fh.fptr; + } + FRESULT res = f_lseek(&_fh, position); + if(res) { + FFSDEBUG("lseek failed (%d, %s)\n", res, FR_ERRORS[res]); + return -1; + } else { + FFSDEBUG("lseek OK, returning %i\n", _fh.fptr); + return _fh.fptr; + } +} + +int FATFileHandle::fsync() { + FFSDEBUG("fsync()\n"); + FRESULT res = f_sync(&_fh); + if (res) { + FFSDEBUG("f_sync() failed (%d, %s)\n", res, FR_ERRORS[res]); + return -1; + } + return 0; +} + +off_t FATFileHandle::flen() { + FFSDEBUG("flen\n"); + return _fh.fsize; +} + +} // namespace mbed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FatFileSystem/FATFileHandle.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,33 @@ +/* mbed Microcontroller Library - FATFileHandle + * Copyright (c) 2008, sford + */ + +#ifndef MBED_FATFILEHANDLE_H +#define MBED_FATFILEHANDLE_H + +#include "FileHandle.h" +#include "ff.h" + +namespace mbed { + +class FATFileHandle : public FileHandle { +public: + + FATFileHandle(FIL fh); + virtual int close(); + virtual ssize_t write(const void* buffer, size_t length); + virtual ssize_t read(void* buffer, size_t length); + virtual int isatty(); + virtual off_t lseek(off_t position, int whence); + virtual int fsync(); + virtual off_t flen(); + +protected: + + FIL _fh; + +}; + +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FatFileSystem/FATFileSystem.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,134 @@ +/* mbed Microcontroller Library - FATFileSystem + * Copyright (c) 2008, sford + */ + +#include "FATFileSystem.h" + +#include "mbed.h" + +#include "FileSystemLike.h" +#include "FATFileHandle.h" +#include "FATDirHandle.h" +#include "ff.h" +//#include "Debug.h" +#include <stdio.h> +#include <stdlib.h> + +DWORD get_fattime (void) { + return 999; +} + +namespace mbed { + +#if FFSDEBUG_ENABLED +static const char *FR_ERRORS[] = { + "FR_OK = 0", + "FR_NOT_READY", + "FR_NO_FILE", + "FR_NO_PATH", + "FR_INVALID_NAME", + "FR_INVALID_DRIVE", + "FR_DENIED", + "FR_EXIST", + "FR_RW_ERROR", + "FR_WRITE_PROTECTED", + "FR_NOT_ENABLED", + "FR_NO_FILESYSTEM", + "FR_INVALID_OBJECT", + "FR_MKFS_ABORTED" +}; +#endif + +FATFileSystem *FATFileSystem::_ffs[_VOLUMES] = {0}; + +FATFileSystem::FATFileSystem(const char* n) : FileSystemLike(n) { + FFSDEBUG("FATFileSystem(%s)\n", n); + for(int i=0; i<_VOLUMES; i++) { + if(_ffs[i] == 0) { + _ffs[i] = this; + _fsid = i; + FFSDEBUG("Mounting [%s] on ffs drive [%d]\n", _name, _fsid); + f_mount(i, &_fs); + return; + } + } + error("Couldn't create %s in FATFileSystem::FATFileSystem\n",n); +} + +FATFileSystem::~FATFileSystem() { + for(int i=0; i<_VOLUMES; i++) { + if(_ffs[i] == this) { + _ffs[i] = 0; + f_mount(i, NULL); + } + } +} + +FileHandle *FATFileSystem::open(const char* name, int flags) { + FFSDEBUG("open(%s) on filesystem [%s], drv [%d]\n", name, _name, _fsid); + char n[64]; + sprintf(n, "%d:/%s", _fsid, name); + + /* POSIX flags -> FatFS open mode */ + BYTE openmode; + if(flags & O_RDWR) { + openmode = FA_READ|FA_WRITE; + } else if(flags & O_WRONLY) { + openmode = FA_WRITE; + } else { + openmode = FA_READ; + } + if(flags & O_CREAT) { + if(flags & O_TRUNC) { + openmode |= FA_CREATE_ALWAYS; + } else { + openmode |= FA_OPEN_ALWAYS; + } + } + + FIL fh; + FRESULT res = f_open(&fh, n, openmode); + if(res) { + FFSDEBUG("f_open('w') failed (%d, %s)\n", res, FR_ERRORS[res]); + return NULL; + } + if(flags & O_APPEND) { + f_lseek(&fh, fh.fsize); + } + return new FATFileHandle(fh); +} + +int FATFileSystem::remove(const char *filename) { + FRESULT res = f_unlink(filename); + if(res) { + FFSDEBUG("f_unlink() failed (%d, %s)\n", res, FR_ERRORS[res]); + return -1; + } + return 0; +} + +int FATFileSystem::format() { + FFSDEBUG("format()\n"); + FRESULT res = f_mkfs(_fsid, 0, 512); // Logical drive number, Partitioning rule, Allocation unit size (bytes per cluster) + if(res) { + FFSDEBUG("f_mkfs() failed (%d, %s)\n", res, FR_ERRORS[res]); + return -1; + } + return 0; +} + +DirHandle *FATFileSystem::opendir(const char *name) { + FATFS_DIR dir; + FRESULT res = f_opendir(&dir, name); + if(res != 0) { + return NULL; + } + return new FATDirHandle(dir); +} + +int FATFileSystem::mkdir(const char *name, mode_t mode) { + FRESULT res = f_mkdir(name); + return res == 0 ? 0 : -1; +} + +} // namespace mbed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FatFileSystem/FATFileSystem.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,61 @@ +/* mbed Microcontroller Library - FATFileSystem + * Copyright (c) 2008, sford + */ + +/* Library: FATFileSystem.h + * A library of stuff to make a fat filesystem on top of a block device + */ + +#ifndef MBED_FATFILESYSTEM_H +#define MBED_FATFILESYSTEM_H + +#ifndef FFSDEBUG_ENABLED +#define FFSDEBUG_ENABLED 0 +#endif + +#if FFSDEBUG_ENABLED +#define FFSDEBUG(FMT, ...) printf(FMT, ##__VA_ARGS__) +#else +#define FFSDEBUG(FMT, ...) +#endif + +#include "FileSystemLike.h" +#include "FileHandle.h" +#include "ff.h" +#include "diskio.h" + +namespace mbed { +/* Class: FATFileSystem + * The class itself + */ +class FATFileSystem : public FileSystemLike { +public: + + FATFileSystem(const char* n); + virtual ~FATFileSystem(); + + /* Function: open + * open a file on the filesystem. never called directly + */ + virtual FileHandle *open(const char* name, int flags); + virtual int remove(const char *filename); + virtual int format(); + virtual DirHandle *opendir(const char *name); + virtual int mkdir(const char *name, mode_t mode); + + FATFS _fs; // Work area (file system object) for logical drive + static FATFileSystem *_ffs[_VOLUMES]; // FATFileSystem objects, as parallel to FatFs drives array + int _fsid; + + virtual int disk_initialize() { return 0; } + virtual int disk_status() { return 0; } + virtual int disk_read(char *buffer, int sector) = 0; + virtual int disk_write(const char *buffer, int sector) = 0; + virtual int disk_sync() { return 0; } + virtual int disk_sectors() = 0; + +}; + +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FatFileSystem/MemFileSystem.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,75 @@ +/* mbed Microcontroller Library - MemFileSystem + * Copyright (c) 2008, sford + */ + + +#ifndef MBED_MEMFILESYSTEM_H +#define MBED_MEMFILESYSTEM_H + +#include "FATFileSystem.h" + +namespace mbed { + +class MemFileSystem : public FATFileSystem { +public: + + // 2000 sectors, each 512 bytes (malloced as required) + char *sectors[2000]; + + MemFileSystem(const char* name) : FATFileSystem(name) { + memset(sectors, 0, sizeof(sectors)); + } + + virtual ~MemFileSystem() { + for(int i = 0; i < 2000; i++) { + if(sectors[i]) { + free(sectors[i]); + } + } + } + + // read a sector in to the buffer, return 0 if ok + virtual int disk_read(char *buffer, int sector) { + if(sectors[sector] == 0) { + // nothing allocated means sector is empty + memset(buffer, 0, 512); + } else { + memcpy(buffer, sectors[sector], 512); + } + return 0; + } + + // write a sector from the buffer, return 0 if ok + virtual int disk_write(const char *buffer, int sector) { + // if buffer is zero deallocate sector + char zero[512]; + memset(zero, 0, 512); + if(memcmp(zero, buffer, 512)==0) { + if(sectors[sector] != 0) { + free(sectors[sector]); + sectors[sector] = 0; + } + return 0; + } + // else allocate a sector if needed, and write + if(sectors[sector] == 0) { + char *sec = (char*)malloc(512); + if(sec==0) { + return 1; // out of memory + } + sectors[sector] = sec; + } + memcpy(sectors[sector], buffer, 512); + return 0; + } + + // return the number of sectors + virtual int disk_sectors() { + return sizeof(sectors)/sizeof(sectors[0]); + } + +}; + +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FatFileSystem/diskio.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,105 @@ +/*-----------------------------------------------------------------------*/ +/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2007 */ +/*-----------------------------------------------------------------------*/ +/* This is a stub disk I/O module that acts as front end of the existing */ +/* disk I/O modules and attach it to FatFs module with common interface. */ +/*-----------------------------------------------------------------------*/ + +#include "diskio.h" +#include <stdio.h> +#include <string.h> +#include "FATFileSystem.h" + +#include "mbed.h" + +DSTATUS disk_initialize ( + BYTE drv /* Physical drive nmuber (0..) */ +) +{ + FFSDEBUG("disk_initialize on drv [%d]\n", drv); + return (DSTATUS)FATFileSystem::_ffs[drv]->disk_initialize(); +} + +DSTATUS disk_status ( + BYTE drv /* Physical drive nmuber (0..) */ +) +{ + FFSDEBUG("disk_status on drv [%d]\n", drv); + return (DSTATUS)FATFileSystem::_ffs[drv]->disk_status(); +} + +DRESULT disk_read ( + BYTE drv, /* Physical drive nmuber (0..) */ + BYTE *buff, /* Data buffer to store read data */ + DWORD sector, /* Sector address (LBA) */ + BYTE count /* Number of sectors to read (1..255) */ +) +{ + FFSDEBUG("disk_read(sector %d, count %d) on drv [%d]\n", sector, count, drv); + for(DWORD s=sector; s<sector+count; s++) { + FFSDEBUG(" disk_read(sector %d)\n", s); + int res = FATFileSystem::_ffs[drv]->disk_read((char*)buff, s); + if(res) { + return RES_PARERR; + } + buff += 512; + } + return RES_OK; +} + +#if _READONLY == 0 +DRESULT disk_write ( + BYTE drv, /* Physical drive nmuber (0..) */ + const BYTE *buff, /* Data to be written */ + DWORD sector, /* Sector address (LBA) */ + BYTE count /* Number of sectors to write (1..255) */ +) +{ + FFSDEBUG("disk_write(sector %d, count %d) on drv [%d]\n", sector, count, drv); + for(DWORD s=sector; s<sector+count; s++) { + FFSDEBUG(" disk_write(sector %d)\n", s); + int res = FATFileSystem::_ffs[drv]->disk_write((char*)buff, s); + if(res) { + return RES_PARERR; + } + buff += 512; + } + return RES_OK; +} +#endif /* _READONLY */ + +DRESULT disk_ioctl ( + BYTE drv, /* Physical drive nmuber (0..) */ + BYTE ctrl, /* Control code */ + void *buff /* Buffer to send/receive control data */ +) +{ + FFSDEBUG("disk_ioctl(%d)\n", ctrl); + switch(ctrl) { + case CTRL_SYNC: + if(FATFileSystem::_ffs[drv] == NULL) { + return RES_NOTRDY; + } else if(FATFileSystem::_ffs[drv]->disk_sync()) { + return RES_ERROR; + } + return RES_OK; + case GET_SECTOR_COUNT: + if(FATFileSystem::_ffs[drv] == NULL) { + return RES_NOTRDY; + } else { + int res = FATFileSystem::_ffs[drv]->disk_sectors(); + if(res > 0) { + *((DWORD*)buff) = res; // minimum allowed + return RES_OK; + } else { + return RES_ERROR; + } + } + case GET_BLOCK_SIZE: + *((DWORD*)buff) = 1; // default when not known + return RES_OK; + + } + return RES_PARERR; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FatFileSystem/diskio.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,78 @@ +/*----------------------------------------------------------------------- +/ Low level disk interface modlue include file +/-----------------------------------------------------------------------*/ + +#ifndef _DISKIO + +#define _READONLY 0 /* 1: Remove write functions */ +#define _USE_IOCTL 1 /* 1: Use disk_ioctl fucntion */ + +#include "integer.h" + + +/* Status of Disk Functions */ +typedef BYTE DSTATUS; + +/* Results of Disk Functions */ +typedef enum { + RES_OK = 0, /* 0: Successful */ + RES_ERROR, /* 1: R/W Error */ + RES_WRPRT, /* 2: Write Protected */ + RES_NOTRDY, /* 3: Not Ready */ + RES_PARERR /* 4: Invalid Parameter */ +} DRESULT; + + +/*---------------------------------------*/ +/* Prototypes for disk control functions */ + +int assign_drives (int, int); +DSTATUS disk_initialize (BYTE); +DSTATUS disk_status (BYTE); +DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE); +#if _READONLY == 0 +DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE); +#endif +DRESULT disk_ioctl (BYTE, BYTE, void*); + + + +/* Disk Status Bits (DSTATUS) */ + +#define STA_NOINIT 0x01 /* Drive not initialized */ +#define STA_NODISK 0x02 /* No medium in the drive */ +#define STA_PROTECT 0x04 /* Write protected */ + + +/* Command code for disk_ioctrl fucntion */ + +/* Generic command (defined for FatFs) */ +#define CTRL_SYNC 0 /* Flush disk cache (for write functions) */ +#define GET_SECTOR_COUNT 1 /* Get media size (for only f_mkfs()) */ +#define GET_SECTOR_SIZE 2 /* Get sector size (for multiple sector size (_MAX_SS >= 1024)) */ +#define GET_BLOCK_SIZE 3 /* Get erase block size (for only f_mkfs()) */ +#define CTRL_ERASE_SECTOR 4 /* Force erased a block of sectors (for only _USE_ERASE) */ + +/* Generic command */ +#define CTRL_POWER 5 /* Get/Set power status */ +#define CTRL_LOCK 6 /* Lock/Unlock media removal */ +#define CTRL_EJECT 7 /* Eject media */ + +/* MMC/SDC specific ioctl command */ +#define MMC_GET_TYPE 10 /* Get card type */ +#define MMC_GET_CSD 11 /* Get CSD */ +#define MMC_GET_CID 12 /* Get CID */ +#define MMC_GET_OCR 13 /* Get OCR */ +#define MMC_GET_SDSTAT 14 /* Get SD status */ + +/* ATA/CF specific ioctl command */ +#define ATA_GET_REV 20 /* Get F/W revision */ +#define ATA_GET_MODEL 21 /* Get model name */ +#define ATA_GET_SN 22 /* Get serial number */ + +/* NAND specific ioctl command */ +#define NAND_FORMAT 30 /* Create physical format */ + + +#define _DISKIO +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FatFileSystem/ff.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,4077 @@ +/*----------------------------------------------------------------------------/ +/ FatFs - FAT file system module R0.09 (C)ChaN, 2011 +/-----------------------------------------------------------------------------/ +/ FatFs module is a generic FAT file system module for small embedded systems. +/ This is a free software that opened for education, research and commercial +/ developments under license policy of following terms. +/ +/ Copyright (C) 2011, ChaN, all right reserved. +/ +/ * The FatFs module is a free software and there is NO WARRANTY. +/ * No restriction on use. You can use, modify and redistribute it for +/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. +/ * Redistributions of source code must retain the above copyright notice. +/ +/-----------------------------------------------------------------------------/ +/ Feb 26,'06 R0.00 Prototype. +/ +/ Apr 29,'06 R0.01 First stable version. +/ +/ Jun 01,'06 R0.02 Added FAT12 support. +/ Removed unbuffered mode. +/ Fixed a problem on small (<32M) partition. +/ Jun 10,'06 R0.02a Added a configuration option (_FS_MINIMUM). +/ +/ Sep 22,'06 R0.03 Added f_rename(). +/ Changed option _FS_MINIMUM to _FS_MINIMIZE. +/ Dec 11,'06 R0.03a Improved cluster scan algorithm to write files fast. +/ Fixed f_mkdir() creates incorrect directory on FAT32. +/ +/ Feb 04,'07 R0.04 Supported multiple drive system. +/ Changed some interfaces for multiple drive system. +/ Changed f_mountdrv() to f_mount(). +/ Added f_mkfs(). +/ Apr 01,'07 R0.04a Supported multiple partitions on a physical drive. +/ Added a capability of extending file size to f_lseek(). +/ Added minimization level 3. +/ Fixed an endian sensitive code in f_mkfs(). +/ May 05,'07 R0.04b Added a configuration option _USE_NTFLAG. +/ Added FSInfo support. +/ Fixed DBCS name can result FR_INVALID_NAME. +/ Fixed short seek (<= csize) collapses the file object. +/ +/ Aug 25,'07 R0.05 Changed arguments of f_read(), f_write() and f_mkfs(). +/ Fixed f_mkfs() on FAT32 creates incorrect FSInfo. +/ Fixed f_mkdir() on FAT32 creates incorrect directory. +/ Feb 03,'08 R0.05a Added f_truncate() and f_utime(). +/ Fixed off by one error at FAT sub-type determination. +/ Fixed btr in f_read() can be mistruncated. +/ Fixed cached sector is not flushed when create and close without write. +/ +/ Apr 01,'08 R0.06 Added fputc(), fputs(), fprintf() and fgets(). +/ Improved performance of f_lseek() on moving to the same or following cluster. +/ +/ Apr 01,'09 R0.07 Merged Tiny-FatFs as a configuration option. (_FS_TINY) +/ Added long file name feature. +/ Added multiple code page feature. +/ Added re-entrancy for multitask operation. +/ Added auto cluster size selection to f_mkfs(). +/ Added rewind option to f_readdir(). +/ Changed result code of critical errors. +/ Renamed string functions to avoid name collision. +/ Apr 14,'09 R0.07a Separated out OS dependent code on reentrant cfg. +/ Added multiple sector size feature. +/ Jun 21,'09 R0.07c Fixed f_unlink() can return FR_OK on error. +/ Fixed wrong cache control in f_lseek(). +/ Added relative path feature. +/ Added f_chdir() and f_chdrive(). +/ Added proper case conversion to extended char. +/ Nov 03,'09 R0.07e Separated out configuration options from ff.h to ffconf.h. +/ Fixed f_unlink() fails to remove a sub-dir on _FS_RPATH. +/ Fixed name matching error on the 13 char boundary. +/ Added a configuration option, _LFN_UNICODE. +/ Changed f_readdir() to return the SFN with always upper case on non-LFN cfg. +/ +/ May 15,'10 R0.08 Added a memory configuration option. (_USE_LFN = 3) +/ Added file lock feature. (_FS_SHARE) +/ Added fast seek feature. (_USE_FASTSEEK) +/ Changed some types on the API, XCHAR->TCHAR. +/ Changed fname member in the FILINFO structure on Unicode cfg. +/ String functions support UTF-8 encoding files on Unicode cfg. +/ Aug 16,'10 R0.08a Added f_getcwd(). (_FS_RPATH = 2) +/ Added sector erase feature. (_USE_ERASE) +/ Moved file lock semaphore table from fs object to the bss. +/ Fixed a wrong directory entry is created on non-LFN cfg when the given name contains ';'. +/ Fixed f_mkfs() creates wrong FAT32 volume. +/ Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write(). +/ f_lseek() reports required table size on creating CLMP. +/ Extended format syntax of f_printf function. +/ Ignores duplicated directory separators in given path names. +/ +/ Sep 06,'11 R0.09 f_mkfs() supports multiple partition to finish the multiple partition feature. +/ Added f_fdisk(). (_MULTI_PARTITION = 2) +/---------------------------------------------------------------------------*/ + +#include "ff.h" /* FatFs configurations and declarations */ +#include "diskio.h" /* Declarations of low level disk I/O functions */ + + +/*-------------------------------------------------------------------------- + + Module Private Definitions + +---------------------------------------------------------------------------*/ + +#if _FATFS != 6502 /* Revision ID */ +#error Wrong include file (ff.h). +#endif + + +/* Definitions on sector size */ +#if _MAX_SS != 512 && _MAX_SS != 1024 && _MAX_SS != 2048 && _MAX_SS != 4096 +#error Wrong sector size. +#endif +#if _MAX_SS != 512 +#define SS(fs) ((fs)->ssize) /* Variable sector size */ +#else +#define SS(fs) 512U /* Fixed sector size */ +#endif + + +/* Reentrancy related */ +#if _FS_REENTRANT +#if _USE_LFN == 1 +#error Static LFN work area must not be used in re-entrant configuration. +#endif +#define ENTER_FF(fs) { if (!lock_fs(fs)) return FR_TIMEOUT; } +#define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; } +#else +#define ENTER_FF(fs) +#define LEAVE_FF(fs, res) return res +#endif + +#define ABORT(fs, res) { fp->flag |= FA__ERROR; LEAVE_FF(fs, res); } + + +/* File shareing feature */ +#if _FS_SHARE +#if _FS_READONLY +#error _FS_SHARE must be 0 on read-only cfg. +#endif +typedef struct { + FATFS *fs; /* File ID 1, volume (NULL:blank entry) */ + DWORD clu; /* File ID 2, directory */ + WORD idx; /* File ID 3, directory index */ + WORD ctr; /* File open counter, 0:none, 0x01..0xFF:read open count, 0x100:write mode */ +} FILESEM; +#endif + + +/* Misc definitions */ +#define LD_CLUST(dir) (((DWORD)LD_WORD(dir+DIR_FstClusHI)<<16) | LD_WORD(dir+DIR_FstClusLO)) +#define ST_CLUST(dir,cl) {ST_WORD(dir+DIR_FstClusLO, cl); ST_WORD(dir+DIR_FstClusHI, (DWORD)cl>>16);} + + +/* DBCS code ranges and SBCS extend char conversion table */ + +#if _CODE_PAGE == 932 /* Japanese Shift-JIS */ +#define _DF1S 0x81 /* DBC 1st byte range 1 start */ +#define _DF1E 0x9F /* DBC 1st byte range 1 end */ +#define _DF2S 0xE0 /* DBC 1st byte range 2 start */ +#define _DF2E 0xFC /* DBC 1st byte range 2 end */ +#define _DS1S 0x40 /* DBC 2nd byte range 1 start */ +#define _DS1E 0x7E /* DBC 2nd byte range 1 end */ +#define _DS2S 0x80 /* DBC 2nd byte range 2 start */ +#define _DS2E 0xFC /* DBC 2nd byte range 2 end */ + +#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */ +#define _DF1S 0x81 +#define _DF1E 0xFE +#define _DS1S 0x40 +#define _DS1E 0x7E +#define _DS2S 0x80 +#define _DS2E 0xFE + +#elif _CODE_PAGE == 949 /* Korean */ +#define _DF1S 0x81 +#define _DF1E 0xFE +#define _DS1S 0x41 +#define _DS1E 0x5A +#define _DS2S 0x61 +#define _DS2E 0x7A +#define _DS3S 0x81 +#define _DS3E 0xFE + +#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */ +#define _DF1S 0x81 +#define _DF1E 0xFE +#define _DS1S 0x40 +#define _DS1E 0x7E +#define _DS2S 0xA1 +#define _DS2E 0xFE + +#elif _CODE_PAGE == 437 /* U.S. (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F,0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 720 /* Arabic (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x45,0x41,0x84,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x49,0x49,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 737 /* Greek (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \ + 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xE7,0xE8,0xF1,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 775 /* Baltic (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 850 /* Multilingual Latin 1 (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 852 /* Latin 2 (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F,0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0x9F, \ + 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF} + +#elif _CODE_PAGE == 855 /* Cyrillic (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F,0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \ + 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \ + 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 857 /* Turkish (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x98,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \ + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0x59,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 858 /* Multilingual Latin 1 + Euro (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 862 /* Hebrew (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 866 /* Russian (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x90,0x91,0x92,0x93,0x9d,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 874 /* Thai (OEM, Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 1250 /* Central Europe (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xA3,0xB4,0xB5,0xB6,0xB7,0xB8,0xA5,0xAA,0xBB,0xBC,0xBD,0xBC,0xAF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} + +#elif _CODE_PAGE == 1251 /* Cyrillic (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x82,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x80,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \ + 0xA0,0xA2,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB2,0xA5,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xA3,0xBD,0xBD,0xAF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF} + +#elif _CODE_PAGE == 1252 /* Latin 1 (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0xAd,0x9B,0x8C,0x9D,0xAE,0x9F, \ + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} + +#elif _CODE_PAGE == 1253 /* Greek (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xA2,0xB8,0xB9,0xBA, \ + 0xE0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xFB,0xBC,0xFD,0xBF,0xFF} + +#elif _CODE_PAGE == 1254 /* Turkish (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x9D,0x9E,0x9F, \ + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} + +#elif _CODE_PAGE == 1255 /* Hebrew (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 1256 /* Arabic (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x8C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x41,0xE1,0x41,0xE3,0xE4,0xE5,0xE6,0x43,0x45,0x45,0x45,0x45,0xEC,0xED,0x49,0x49,0xF0,0xF1,0xF2,0xF3,0x4F,0xF5,0xF6,0xF7,0xF8,0x55,0xFA,0x55,0x55,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 1257 /* Baltic (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xBC,0xBD,0xBE,0xAF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} + +#elif _CODE_PAGE == 1258 /* Vietnam (OEM, Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0xAC,0x9D,0x9E,0x9F, \ + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xEC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xFE,0x9F} + +#elif _CODE_PAGE == 1 /* ASCII (for only non-LFN cfg) */ +#if _USE_LFN +#error Cannot use LFN feature without valid code page. +#endif +#define _DF1S 0 + +#else +#error Unknown code page + +#endif + + +/* Character code support macros */ +#define IsUpper(c) (((c)>='A')&&((c)<='Z')) +#define IsLower(c) (((c)>='a')&&((c)<='z')) +#define IsDigit(c) (((c)>='0')&&((c)<='9')) + +#if _DF1S /* Code page is DBCS */ + +#ifdef _DF2S /* Two 1st byte areas */ +#define IsDBCS1(c) (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E)) +#else /* One 1st byte area */ +#define IsDBCS1(c) ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) +#endif + +#ifdef _DS3S /* Three 2nd byte areas */ +#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E)) +#else /* Two 2nd byte areas */ +#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E)) +#endif + +#else /* Code page is SBCS */ + +#define IsDBCS1(c) 0 +#define IsDBCS2(c) 0 + +#endif /* _DF1S */ + + +/* Name status flags */ +#define NS 11 /* Index of name status byte in fn[] */ +#define NS_LOSS 0x01 /* Out of 8.3 format */ +#define NS_LFN 0x02 /* Force to create LFN entry */ +#define NS_LAST 0x04 /* Last segment */ +#define NS_BODY 0x08 /* Lower case flag (body) */ +#define NS_EXT 0x10 /* Lower case flag (ext) */ +#define NS_DOT 0x20 /* Dot entry */ + + +/* FAT sub-type boundaries */ +/* Note that the FAT spec by Microsoft says 4085 but Windows works with 4087! */ +#define MIN_FAT16 4086 /* Minimum number of clusters for FAT16 */ +#define MIN_FAT32 65526 /* Minimum number of clusters for FAT32 */ + + +/* FatFs refers the members in the FAT structures as byte array instead of +/ structure member because the structure is not binary compatible between +/ different platforms */ + +#define BS_jmpBoot 0 /* Jump instruction (3) */ +#define BS_OEMName 3 /* OEM name (8) */ +#define BPB_BytsPerSec 11 /* Sector size [byte] (2) */ +#define BPB_SecPerClus 13 /* Cluster size [sector] (1) */ +#define BPB_RsvdSecCnt 14 /* Size of reserved area [sector] (2) */ +#define BPB_NumFATs 16 /* Number of FAT copies (1) */ +#define BPB_RootEntCnt 17 /* Number of root dir entries for FAT12/16 (2) */ +#define BPB_TotSec16 19 /* Volume size [sector] (2) */ +#define BPB_Media 21 /* Media descriptor (1) */ +#define BPB_FATSz16 22 /* FAT size [sector] (2) */ +#define BPB_SecPerTrk 24 /* Track size [sector] (2) */ +#define BPB_NumHeads 26 /* Number of heads (2) */ +#define BPB_HiddSec 28 /* Number of special hidden sectors (4) */ +#define BPB_TotSec32 32 /* Volume size [sector] (4) */ +#define BS_DrvNum 36 /* Physical drive number (2) */ +#define BS_BootSig 38 /* Extended boot signature (1) */ +#define BS_VolID 39 /* Volume serial number (4) */ +#define BS_VolLab 43 /* Volume label (8) */ +#define BS_FilSysType 54 /* File system type (1) */ +#define BPB_FATSz32 36 /* FAT size [sector] (4) */ +#define BPB_ExtFlags 40 /* Extended flags (2) */ +#define BPB_FSVer 42 /* File system version (2) */ +#define BPB_RootClus 44 /* Root dir first cluster (4) */ +#define BPB_FSInfo 48 /* Offset of FSInfo sector (2) */ +#define BPB_BkBootSec 50 /* Offset of backup boot sectot (2) */ +#define BS_DrvNum32 64 /* Physical drive number (2) */ +#define BS_BootSig32 66 /* Extended boot signature (1) */ +#define BS_VolID32 67 /* Volume serial number (4) */ +#define BS_VolLab32 71 /* Volume label (8) */ +#define BS_FilSysType32 82 /* File system type (1) */ +#define FSI_LeadSig 0 /* FSI: Leading signature (4) */ +#define FSI_StrucSig 484 /* FSI: Structure signature (4) */ +#define FSI_Free_Count 488 /* FSI: Number of free clusters (4) */ +#define FSI_Nxt_Free 492 /* FSI: Last allocated cluster (4) */ +#define MBR_Table 446 /* MBR: Partition table offset (2) */ +#define SZ_PTE 16 /* MBR: Size of a partition table entry */ +#define BS_55AA 510 /* Boot sector signature (2) */ + +#define DIR_Name 0 /* Short file name (11) */ +#define DIR_Attr 11 /* Attribute (1) */ +#define DIR_NTres 12 /* NT flag (1) */ +#define DIR_CrtTime 14 /* Created time (2) */ +#define DIR_CrtDate 16 /* Created date (2) */ +#define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (2) */ +#define DIR_WrtTime 22 /* Modified time (2) */ +#define DIR_WrtDate 24 /* Modified date (2) */ +#define DIR_FstClusLO 26 /* Lower 16-bit of first cluster (2) */ +#define DIR_FileSize 28 /* File size (4) */ +#define LDIR_Ord 0 /* LFN entry order and LLE flag (1) */ +#define LDIR_Attr 11 /* LFN attribute (1) */ +#define LDIR_Type 12 /* LFN type (1) */ +#define LDIR_Chksum 13 /* Sum of corresponding SFN entry */ +#define LDIR_FstClusLO 26 /* Filled by zero (0) */ +#define SZ_DIR 32 /* Size of a directory entry */ +#define LLE 0x40 /* Last long entry flag in LDIR_Ord */ +#define DDE 0xE5 /* Deleted directory enrty mark in DIR_Name[0] */ +#define NDDE 0x05 /* Replacement of a character collides with DDE */ + + +/*------------------------------------------------------------*/ +/* Module private work area */ +/*------------------------------------------------------------*/ +/* Note that uninitialized variables with static duration are +/ zeroed/nulled at start-up. If not, the compiler or start-up +/ routine is out of ANSI-C standard. +*/ + +#if _VOLUMES +static +FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */ +#else +#error Number of volumes must not be 0. +#endif + +static +WORD Fsid; /* File system mount ID */ + +#if _FS_RPATH +static +BYTE CurrVol; /* Current drive */ +#endif + +#if _FS_SHARE +static +FILESEM Files[_FS_SHARE]; /* File lock semaphores */ +#endif + +#if _USE_LFN == 0 /* No LFN feature */ +#define DEF_NAMEBUF BYTE sfn[12] +#define INIT_BUF(dobj) (dobj).fn = sfn +#define FREE_BUF() + +#elif _USE_LFN == 1 /* LFN feature with static working buffer */ +static WCHAR LfnBuf[_MAX_LFN+1]; +#define DEF_NAMEBUF BYTE sfn[12] +#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = LfnBuf; } +#define FREE_BUF() + +#elif _USE_LFN == 2 /* LFN feature with dynamic working buffer on the stack */ +#define DEF_NAMEBUF BYTE sfn[12]; WCHAR lbuf[_MAX_LFN+1] +#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = lbuf; } +#define FREE_BUF() + +#elif _USE_LFN == 3 /* LFN feature with dynamic working buffer on the heap */ +#define DEF_NAMEBUF BYTE sfn[12]; WCHAR *lfn +#define INIT_BUF(dobj) { lfn = ff_memalloc((_MAX_LFN + 1) * 2); \ + if (!lfn) LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); \ + (dobj).lfn = lfn; (dobj).fn = sfn; } +#define FREE_BUF() ff_memfree(lfn) + +#else +#error Wrong LFN configuration. +#endif + + + + +/*-------------------------------------------------------------------------- + + Module Private Functions + +---------------------------------------------------------------------------*/ + + +/*-----------------------------------------------------------------------*/ +/* String functions */ +/*-----------------------------------------------------------------------*/ + +/* Copy memory to memory */ +static +void mem_cpy (void* dst, const void* src, UINT cnt) { + BYTE *d = (BYTE*)dst; + const BYTE *s = (const BYTE*)src; + +#if _WORD_ACCESS == 1 + while (cnt >= sizeof(int)) { + *(int*)d = *(int*)s; + d += sizeof(int); s += sizeof(int); + cnt -= sizeof(int); + } +#endif + while (cnt--) + *d++ = *s++; +} + +/* Fill memory */ +static +void mem_set (void* dst, int val, UINT cnt) { + BYTE *d = (BYTE*)dst; + + while (cnt--) + *d++ = (BYTE)val; +} + +/* Compare memory to memory */ +static +int mem_cmp (const void* dst, const void* src, UINT cnt) { + const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src; + int r = 0; + + while (cnt-- && (r = *d++ - *s++) == 0) ; + return r; +} + +/* Check if chr is contained in the string */ +static +int chk_chr (const char* str, int chr) { + while (*str && *str != chr) str++; + return *str; +} + + + +/*-----------------------------------------------------------------------*/ +/* Request/Release grant to access the volume */ +/*-----------------------------------------------------------------------*/ +#if _FS_REENTRANT + +static +int lock_fs ( + FATFS *fs /* File system object */ +) +{ + return ff_req_grant(fs->sobj); +} + + +static +void unlock_fs ( + FATFS *fs, /* File system object */ + FRESULT res /* Result code to be returned */ +) +{ + if (res != FR_NOT_ENABLED && + res != FR_INVALID_DRIVE && + res != FR_INVALID_OBJECT && + res != FR_TIMEOUT) { + ff_rel_grant(fs->sobj); + } +} +#endif + + + +/*-----------------------------------------------------------------------*/ +/* File shareing control functions */ +/*-----------------------------------------------------------------------*/ +#if _FS_SHARE + +static +FRESULT chk_lock ( /* Check if the file can be accessed */ + FATFS_DIR* dj, /* Directory object pointing the file to be checked */ + int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */ +) +{ + UINT i, be; + + /* Search file semaphore table */ + for (i = be = 0; i < _FS_SHARE; i++) { + if (Files[i].fs) { /* Existing entry */ + if (Files[i].fs == dj->fs && /* Check if the file matched with an open file */ + Files[i].clu == dj->sclust && + Files[i].idx == dj->index) break; + } else { /* Blank entry */ + be++; + } + } + if (i == _FS_SHARE) /* The file is not opened */ + return (be || acc == 2) ? FR_OK : FR_TOO_MANY_OPEN_FILES; /* Is there a blank entry for new file? */ + + /* The file has been opened. Reject any open against writing file and all write mode open */ + return (acc || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK; +} + + +static +int enq_lock (void) /* Check if an entry is available for a new file */ +{ + UINT i; + + for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ; + return (i == _FS_SHARE) ? 0 : 1; +} + + +static +UINT inc_lock ( /* Increment file open counter and returns its index (0:int error) */ + FATFS_DIR* dj, /* Directory object pointing the file to register or increment */ + int acc /* Desired access mode (0:Read, !0:Write) */ +) +{ + UINT i; + + + for (i = 0; i < _FS_SHARE; i++) { /* Find the file */ + if (Files[i].fs == dj->fs && + Files[i].clu == dj->sclust && + Files[i].idx == dj->index) break; + } + + if (i == _FS_SHARE) { /* Not opened. Register it as new. */ + for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ; + if (i == _FS_SHARE) return 0; /* No space to register (int err) */ + Files[i].fs = dj->fs; + Files[i].clu = dj->sclust; + Files[i].idx = dj->index; + Files[i].ctr = 0; + } + + if (acc && Files[i].ctr) return 0; /* Access violation (int err) */ + + Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1; /* Set semaphore value */ + + return i + 1; +} + + +static +FRESULT dec_lock ( /* Decrement file open counter */ + UINT i /* Semaphore index */ +) +{ + WORD n; + FRESULT res; + + + if (--i < _FS_SHARE) { + n = Files[i].ctr; + if (n == 0x100) n = 0; + if (n) n--; + Files[i].ctr = n; + if (!n) Files[i].fs = 0; + res = FR_OK; + } else { + res = FR_INT_ERR; + } + return res; +} + + +static +void clear_lock ( /* Clear lock entries of the volume */ + FATFS *fs +) +{ + UINT i; + + for (i = 0; i < _FS_SHARE; i++) { + if (Files[i].fs == fs) Files[i].fs = 0; + } +} +#endif + + + +/*-----------------------------------------------------------------------*/ +/* Change window offset */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT move_window ( + FATFS *fs, /* File system object */ + DWORD sector /* Sector number to make appearance in the fs->win[] */ +) /* Move to zero only writes back dirty window */ +{ + DWORD wsect; + + + wsect = fs->winsect; + if (wsect != sector) { /* Changed current window */ +#if !_FS_READONLY + if (fs->wflag) { /* Write back dirty window if needed */ + if (disk_write(fs->drv, fs->win, wsect, 1) != RES_OK) + return FR_DISK_ERR; + fs->wflag = 0; + if (wsect < (fs->fatbase + fs->fsize)) { /* In FAT area */ + BYTE nf; + for (nf = fs->n_fats; nf > 1; nf--) { /* Reflect the change to all FAT copies */ + wsect += fs->fsize; + disk_write(fs->drv, fs->win, wsect, 1); + } + } + } +#endif + if (sector) { + if (disk_read(fs->drv, fs->win, sector, 1) != RES_OK) + return FR_DISK_ERR; + fs->winsect = sector; + } + } + + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Clean-up cached data */ +/*-----------------------------------------------------------------------*/ +#if !_FS_READONLY +static +FRESULT sync ( /* FR_OK: successful, FR_DISK_ERR: failed */ + FATFS *fs /* File system object */ +) +{ + FRESULT res; + + + res = move_window(fs, 0); + if (res == FR_OK) { + /* Update FSInfo sector if needed */ + if (fs->fs_type == FS_FAT32 && fs->fsi_flag) { + fs->winsect = 0; + /* Create FSInfo structure */ + mem_set(fs->win, 0, 512); + ST_WORD(fs->win+BS_55AA, 0xAA55); + ST_DWORD(fs->win+FSI_LeadSig, 0x41615252); + ST_DWORD(fs->win+FSI_StrucSig, 0x61417272); + ST_DWORD(fs->win+FSI_Free_Count, fs->free_clust); + ST_DWORD(fs->win+FSI_Nxt_Free, fs->last_clust); + /* Write it into the FSInfo sector */ + disk_write(fs->drv, fs->win, fs->fsi_sector, 1); + fs->fsi_flag = 0; + } + /* Make sure that no pending write process in the physical drive */ + if (disk_ioctl(fs->drv, CTRL_SYNC, 0) != RES_OK) + res = FR_DISK_ERR; + } + + return res; +} +#endif + + + + +/*-----------------------------------------------------------------------*/ +/* Get sector# from cluster# */ +/*-----------------------------------------------------------------------*/ + + +DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */ + FATFS *fs, /* File system object */ + DWORD clst /* Cluster# to be converted */ +) +{ + clst -= 2; + if (clst >= (fs->n_fatent - 2)) return 0; /* Invalid cluster# */ + return clst * fs->csize + fs->database; +} + + + + +/*-----------------------------------------------------------------------*/ +/* FAT access - Read value of a FAT entry */ +/*-----------------------------------------------------------------------*/ + + +DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status */ + FATFS *fs, /* File system object */ + DWORD clst /* Cluster# to get the link information */ +) +{ + UINT wc, bc; + BYTE *p; + + + if (clst < 2 || clst >= fs->n_fatent) /* Chack range */ + return 1; + + switch (fs->fs_type) { + case FS_FAT12 : + bc = (UINT)clst; bc += bc / 2; + if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break; + wc = fs->win[bc % SS(fs)]; bc++; + if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break; + wc |= fs->win[bc % SS(fs)] << 8; + return (clst & 1) ? (wc >> 4) : (wc & 0xFFF); + + case FS_FAT16 : + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)))) break; + p = &fs->win[clst * 2 % SS(fs)]; + return LD_WORD(p); + + case FS_FAT32 : + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)))) break; + p = &fs->win[clst * 4 % SS(fs)]; + return LD_DWORD(p) & 0x0FFFFFFF; + } + + return 0xFFFFFFFF; /* An error occurred at the disk I/O layer */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* FAT access - Change value of a FAT entry */ +/*-----------------------------------------------------------------------*/ +#if !_FS_READONLY + +FRESULT put_fat ( + FATFS *fs, /* File system object */ + DWORD clst, /* Cluster# to be changed in range of 2 to fs->n_fatent - 1 */ + DWORD val /* New value to mark the cluster */ +) +{ + UINT bc; + BYTE *p; + FRESULT res; + + + if (clst < 2 || clst >= fs->n_fatent) { /* Check range */ + res = FR_INT_ERR; + + } else { + switch (fs->fs_type) { + case FS_FAT12 : + bc = clst; bc += bc / 2; + res = move_window(fs, fs->fatbase + (bc / SS(fs))); + if (res != FR_OK) break; + p = &fs->win[bc % SS(fs)]; + *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val; + bc++; + fs->wflag = 1; + res = move_window(fs, fs->fatbase + (bc / SS(fs))); + if (res != FR_OK) break; + p = &fs->win[bc % SS(fs)]; + *p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F)); + break; + + case FS_FAT16 : + res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))); + if (res != FR_OK) break; + p = &fs->win[clst * 2 % SS(fs)]; + ST_WORD(p, (WORD)val); + break; + + case FS_FAT32 : + res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))); + if (res != FR_OK) break; + p = &fs->win[clst * 4 % SS(fs)]; + val |= LD_DWORD(p) & 0xF0000000; + ST_DWORD(p, val); + break; + + default : + res = FR_INT_ERR; + } + fs->wflag = 1; + } + + return res; +} +#endif /* !_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* FAT handling - Remove a cluster chain */ +/*-----------------------------------------------------------------------*/ +#if !_FS_READONLY +static +FRESULT remove_chain ( + FATFS *fs, /* File system object */ + DWORD clst /* Cluster# to remove a chain from */ +) +{ + FRESULT res; + DWORD nxt; +#if _USE_ERASE + DWORD scl = clst, ecl = clst, resion[2]; +#endif + + if (clst < 2 || clst >= fs->n_fatent) { /* Check range */ + res = FR_INT_ERR; + + } else { + res = FR_OK; + while (clst < fs->n_fatent) { /* Not a last link? */ + nxt = get_fat(fs, clst); /* Get cluster status */ + if (nxt == 0) break; /* Empty cluster? */ + if (nxt == 1) { res = FR_INT_ERR; break; } /* Internal error? */ + if (nxt == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } /* Disk error? */ + res = put_fat(fs, clst, 0); /* Mark the cluster "empty" */ + if (res != FR_OK) break; + if (fs->free_clust != 0xFFFFFFFF) { /* Update FSInfo */ + fs->free_clust++; + fs->fsi_flag = 1; + } +#if _USE_ERASE + if (ecl + 1 == nxt) { /* Next cluster is contiguous */ + ecl = nxt; + } else { /* End of contiguous clusters */ + resion[0] = clust2sect(fs, scl); /* Start sector */ + resion[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */ + disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, resion); /* Erase the block */ + scl = ecl = nxt; + } +#endif + clst = nxt; /* Next cluster */ + } + } + + return res; +} +#endif + + + + +/*-----------------------------------------------------------------------*/ +/* FAT handling - Stretch or Create a cluster chain */ +/*-----------------------------------------------------------------------*/ +#if !_FS_READONLY +static +DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */ + FATFS *fs, /* File system object */ + DWORD clst /* Cluster# to stretch. 0 means create a new chain. */ +) +{ + DWORD cs, ncl, scl; + FRESULT res; + + + if (clst == 0) { /* Create a new chain */ + scl = fs->last_clust; /* Get suggested start point */ + if (!scl || scl >= fs->n_fatent) scl = 1; + } + else { /* Stretch the current chain */ + cs = get_fat(fs, clst); /* Check the cluster status */ + if (cs < 2) return 1; /* It is an invalid cluster */ + if (cs < fs->n_fatent) return cs; /* It is already followed by next cluster */ + scl = clst; + } + + ncl = scl; /* Start cluster */ + for (;;) { + ncl++; /* Next cluster */ + if (ncl >= fs->n_fatent) { /* Wrap around */ + ncl = 2; + if (ncl > scl) return 0; /* No free cluster */ + } + cs = get_fat(fs, ncl); /* Get the cluster status */ + if (cs == 0) break; /* Found a free cluster */ + if (cs == 0xFFFFFFFF || cs == 1)/* An error occurred */ + return cs; + if (ncl == scl) return 0; /* No free cluster */ + } + + res = put_fat(fs, ncl, 0x0FFFFFFF); /* Mark the new cluster "last link" */ + if (res == FR_OK && clst != 0) { + res = put_fat(fs, clst, ncl); /* Link it to the previous one if needed */ + } + if (res == FR_OK) { + fs->last_clust = ncl; /* Update FSINFO */ + if (fs->free_clust != 0xFFFFFFFF) { + fs->free_clust--; + fs->fsi_flag = 1; + } + } else { + ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1; + } + + return ncl; /* Return new cluster number or error code */ +} +#endif /* !_FS_READONLY */ + + + +/*-----------------------------------------------------------------------*/ +/* FAT handling - Convert offset into cluster with link map table */ +/*-----------------------------------------------------------------------*/ + +#if _USE_FASTSEEK +static +DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */ + FIL* fp, /* Pointer to the file object */ + DWORD ofs /* File offset to be converted to cluster# */ +) +{ + DWORD cl, ncl, *tbl; + + + tbl = fp->cltbl + 1; /* Top of CLMT */ + cl = ofs / SS(fp->fs) / fp->fs->csize; /* Cluster order from top of the file */ + for (;;) { + ncl = *tbl++; /* Number of cluters in the fragment */ + if (!ncl) return 0; /* End of table? (error) */ + if (cl < ncl) break; /* In this fragment? */ + cl -= ncl; tbl++; /* Next fragment */ + } + return cl + *tbl; /* Return the cluster number */ +} +#endif /* _USE_FASTSEEK */ + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Set directory index */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT dir_sdi ( + FATFS_DIR *dj, /* Pointer to directory object */ + WORD idx /* Directory index number */ +) +{ + DWORD clst; + WORD ic; + + + dj->index = idx; + clst = dj->sclust; + if (clst == 1 || clst >= dj->fs->n_fatent) /* Check start cluster range */ + return FR_INT_ERR; + if (!clst && dj->fs->fs_type == FS_FAT32) /* Replace cluster# 0 with root cluster# if in FAT32 */ + clst = dj->fs->dirbase; + + if (clst == 0) { /* Static table (root-dir in FAT12/16) */ + dj->clust = clst; + if (idx >= dj->fs->n_rootdir) /* Index is out of range */ + return FR_INT_ERR; + dj->sect = dj->fs->dirbase + idx / (SS(dj->fs) / SZ_DIR); /* Sector# */ + } + else { /* Dynamic table (sub-dirs or root-dir in FAT32) */ + ic = SS(dj->fs) / SZ_DIR * dj->fs->csize; /* Entries per cluster */ + while (idx >= ic) { /* Follow cluster chain */ + clst = get_fat(dj->fs, clst); /* Get next cluster */ + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ + if (clst < 2 || clst >= dj->fs->n_fatent) /* Reached to end of table or int error */ + return FR_INT_ERR; + idx -= ic; + } + dj->clust = clst; + dj->sect = clust2sect(dj->fs, clst) + idx / (SS(dj->fs) / SZ_DIR); /* Sector# */ + } + + dj->dir = dj->fs->win + (idx % (SS(dj->fs) / SZ_DIR)) * SZ_DIR; /* Ptr to the entry in the sector */ + + return FR_OK; /* Seek succeeded */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Move directory index next */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT and could not stretch */ + FATFS_DIR *dj, /* Pointer to directory object */ + int stretch /* 0: Do not stretch table, 1: Stretch table if needed */ +) +{ + DWORD clst; + WORD i; + + + stretch = stretch; /* To suppress warning on read-only cfg. */ + i = dj->index + 1; + if (!i || !dj->sect) /* Report EOT when index has reached 65535 */ + return FR_NO_FILE; + + if (!(i % (SS(dj->fs) / SZ_DIR))) { /* Sector changed? */ + dj->sect++; /* Next sector */ + + if (dj->clust == 0) { /* Static table */ + if (i >= dj->fs->n_rootdir) /* Report EOT when end of table */ + return FR_NO_FILE; + } + else { /* Dynamic table */ + if (((i / (SS(dj->fs) / SZ_DIR)) & (dj->fs->csize - 1)) == 0) { /* Cluster changed? */ + clst = get_fat(dj->fs, dj->clust); /* Get next cluster */ + if (clst <= 1) return FR_INT_ERR; + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; + if (clst >= dj->fs->n_fatent) { /* When it reached end of dynamic table */ +#if !_FS_READONLY + BYTE c; + if (!stretch) return FR_NO_FILE; /* When do not stretch, report EOT */ + clst = create_chain(dj->fs, dj->clust); /* Stretch cluster chain */ + if (clst == 0) return FR_DENIED; /* No free cluster */ + if (clst == 1) return FR_INT_ERR; + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; + /* Clean-up stretched table */ + if (move_window(dj->fs, 0)) return FR_DISK_ERR; /* Flush active window */ + mem_set(dj->fs->win, 0, SS(dj->fs)); /* Clear window buffer */ + dj->fs->winsect = clust2sect(dj->fs, clst); /* Cluster start sector */ + for (c = 0; c < dj->fs->csize; c++) { /* Fill the new cluster with 0 */ + dj->fs->wflag = 1; + if (move_window(dj->fs, 0)) return FR_DISK_ERR; + dj->fs->winsect++; + } + dj->fs->winsect -= c; /* Rewind window address */ +#else + return FR_NO_FILE; /* Report EOT */ +#endif + } + dj->clust = clst; /* Initialize data for new cluster */ + dj->sect = clust2sect(dj->fs, clst); + } + } + } + + dj->index = i; + dj->dir = dj->fs->win + (i % (SS(dj->fs) / SZ_DIR)) * SZ_DIR; + + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* LFN handling - Test/Pick/Fit an LFN segment from/to directory entry */ +/*-----------------------------------------------------------------------*/ +#if _USE_LFN +static +const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; /* Offset of LFN chars in the directory entry */ + + +static +int cmp_lfn ( /* 1:Matched, 0:Not matched */ + WCHAR *lfnbuf, /* Pointer to the LFN to be compared */ + BYTE *dir /* Pointer to the directory entry containing a part of LFN */ +) +{ + UINT i, s; + WCHAR wc, uc; + + + i = ((dir[LDIR_Ord] & ~LLE) - 1) * 13; /* Get offset in the LFN buffer */ + s = 0; wc = 1; + do { + uc = LD_WORD(dir+LfnOfs[s]); /* Pick an LFN character from the entry */ + if (wc) { /* Last char has not been processed */ + wc = ff_wtoupper(uc); /* Convert it to upper case */ + if (i >= _MAX_LFN || wc != ff_wtoupper(lfnbuf[i++])) /* Compare it */ + return 0; /* Not matched */ + } else { + if (uc != 0xFFFF) return 0; /* Check filler */ + } + } while (++s < 13); /* Repeat until all chars in the entry are checked */ + + if ((dir[LDIR_Ord] & LLE) && wc && lfnbuf[i]) /* Last segment matched but different length */ + return 0; + + return 1; /* The part of LFN matched */ +} + + + +static +int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */ + WCHAR *lfnbuf, /* Pointer to the Unicode-LFN buffer */ + BYTE *dir /* Pointer to the directory entry */ +) +{ + UINT i, s; + WCHAR wc, uc; + + + i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */ + + s = 0; wc = 1; + do { + uc = LD_WORD(dir+LfnOfs[s]); /* Pick an LFN character from the entry */ + if (wc) { /* Last char has not been processed */ + if (i >= _MAX_LFN) return 0; /* Buffer overflow? */ + lfnbuf[i++] = wc = uc; /* Store it */ + } else { + if (uc != 0xFFFF) return 0; /* Check filler */ + } + } while (++s < 13); /* Read all character in the entry */ + + if (dir[LDIR_Ord] & LLE) { /* Put terminator if it is the last LFN part */ + if (i >= _MAX_LFN) return 0; /* Buffer overflow? */ + lfnbuf[i] = 0; + } + + return 1; +} + + +#if !_FS_READONLY +static +void fit_lfn ( + const WCHAR *lfnbuf, /* Pointer to the LFN buffer */ + BYTE *dir, /* Pointer to the directory entry */ + BYTE ord, /* LFN order (1-20) */ + BYTE sum /* SFN sum */ +) +{ + UINT i, s; + WCHAR wc; + + + dir[LDIR_Chksum] = sum; /* Set check sum */ + dir[LDIR_Attr] = AM_LFN; /* Set attribute. LFN entry */ + dir[LDIR_Type] = 0; + ST_WORD(dir+LDIR_FstClusLO, 0); + + i = (ord - 1) * 13; /* Get offset in the LFN buffer */ + s = wc = 0; + do { + if (wc != 0xFFFF) wc = lfnbuf[i++]; /* Get an effective char */ + ST_WORD(dir+LfnOfs[s], wc); /* Put it */ + if (!wc) wc = 0xFFFF; /* Padding chars following last char */ + } while (++s < 13); + if (wc == 0xFFFF || !lfnbuf[i]) ord |= LLE; /* Bottom LFN part is the start of LFN sequence */ + dir[LDIR_Ord] = ord; /* Set the LFN order */ +} + +#endif +#endif + + + +/*-----------------------------------------------------------------------*/ +/* Create numbered name */ +/*-----------------------------------------------------------------------*/ +#if _USE_LFN +void gen_numname ( + BYTE *dst, /* Pointer to generated SFN */ + const BYTE *src, /* Pointer to source SFN to be modified */ + const WCHAR *lfn, /* Pointer to LFN */ + WORD seq /* Sequence number */ +) +{ + BYTE ns[8], c; + UINT i, j; + + + mem_cpy(dst, src, 11); + + if (seq > 5) { /* On many collisions, generate a hash number instead of sequential number */ + do seq = (seq >> 1) + (seq << 15) + (WORD)*lfn++; while (*lfn); + } + + /* itoa (hexdecimal) */ + i = 7; + do { + c = (seq % 16) + '0'; + if (c > '9') c += 7; + ns[i--] = c; + seq /= 16; + } while (seq); + ns[i] = '~'; + + /* Append the number */ + for (j = 0; j < i && dst[j] != ' '; j++) { + if (IsDBCS1(dst[j])) { + if (j == i - 1) break; + j++; + } + } + do { + dst[j++] = (i < 8) ? ns[i++] : ' '; + } while (j < 8); +} +#endif + + + + +/*-----------------------------------------------------------------------*/ +/* Calculate sum of an SFN */ +/*-----------------------------------------------------------------------*/ +#if _USE_LFN +static +BYTE sum_sfn ( + const BYTE *dir /* Ptr to directory entry */ +) +{ + BYTE sum = 0; + UINT n = 11; + + do sum = (sum >> 1) + (sum << 7) + *dir++; while (--n); + return sum; +} +#endif + + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Find an object in the directory */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT dir_find ( + FATFS_DIR *dj /* Pointer to the directory object linked to the file name */ +) +{ + FRESULT res; + BYTE c, *dir; +#if _USE_LFN + BYTE a, ord, sum; +#endif + + res = dir_sdi(dj, 0); /* Rewind directory object */ + if (res != FR_OK) return res; + +#if _USE_LFN + ord = sum = 0xFF; +#endif + do { + res = move_window(dj->fs, dj->sect); + if (res != FR_OK) break; + dir = dj->dir; /* Ptr to the directory entry of current index */ + c = dir[DIR_Name]; + if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ +#if _USE_LFN /* LFN configuration */ + a = dir[DIR_Attr] & AM_MASK; + if (c == DDE || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ + ord = 0xFF; + } else { + if (a == AM_LFN) { /* An LFN entry is found */ + if (dj->lfn) { + if (c & LLE) { /* Is it start of LFN sequence? */ + sum = dir[LDIR_Chksum]; + c &= ~LLE; ord = c; /* LFN start order */ + dj->lfn_idx = dj->index; + } + /* Check validity of the LFN entry and compare it with given name */ + ord = (c == ord && sum == dir[LDIR_Chksum] && cmp_lfn(dj->lfn, dir)) ? ord - 1 : 0xFF; + } + } else { /* An SFN entry is found */ + if (!ord && sum == sum_sfn(dir)) break; /* LFN matched? */ + ord = 0xFF; dj->lfn_idx = 0xFFFF; /* Reset LFN sequence */ + if (!(dj->fn[NS] & NS_LOSS) && !mem_cmp(dir, dj->fn, 11)) break; /* SFN matched? */ + } + } +#else /* Non LFN configuration */ + if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dj->fn, 11)) /* Is it a valid entry? */ + break; +#endif + res = dir_next(dj, 0); /* Next entry */ + } while (res == FR_OK); + + return res; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Read an object from the directory */ +/*-----------------------------------------------------------------------*/ +#if _FS_MINIMIZE <= 1 +static +FRESULT dir_read ( + FATFS_DIR *dj /* Pointer to the directory object that pointing the entry to be read */ +) +{ + FRESULT res; + BYTE c, *dir; +#if _USE_LFN + BYTE a, ord = 0xFF, sum = 0xFF; +#endif + + res = FR_NO_FILE; + while (dj->sect) { + res = move_window(dj->fs, dj->sect); + if (res != FR_OK) break; + dir = dj->dir; /* Ptr to the directory entry of current index */ + c = dir[DIR_Name]; + if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ +#if _USE_LFN /* LFN configuration */ + a = dir[DIR_Attr] & AM_MASK; + if (c == DDE || (!_FS_RPATH && c == '.') || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ + ord = 0xFF; + } else { + if (a == AM_LFN) { /* An LFN entry is found */ + if (c & LLE) { /* Is it start of LFN sequence? */ + sum = dir[LDIR_Chksum]; + c &= ~LLE; ord = c; + dj->lfn_idx = dj->index; + } + /* Check LFN validity and capture it */ + ord = (c == ord && sum == dir[LDIR_Chksum] && pick_lfn(dj->lfn, dir)) ? ord - 1 : 0xFF; + } else { /* An SFN entry is found */ + if (ord || sum != sum_sfn(dir)) /* Is there a valid LFN? */ + dj->lfn_idx = 0xFFFF; /* It has no LFN. */ + break; + } + } +#else /* Non LFN configuration */ + if (c != DDE && (_FS_RPATH || c != '.') && !(dir[DIR_Attr] & AM_VOL)) /* Is it a valid entry? */ + break; +#endif + res = dir_next(dj, 0); /* Next entry */ + if (res != FR_OK) break; + } + + if (res != FR_OK) dj->sect = 0; + + return res; +} +#endif + + + +/*-----------------------------------------------------------------------*/ +/* Register an object to the directory */ +/*-----------------------------------------------------------------------*/ +#if !_FS_READONLY +static +FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many SFN collision, FR_DISK_ERR:Disk error */ + FATFS_DIR *dj /* Target directory with object name to be created */ +) +{ + FRESULT res; + BYTE c, *dir; +#if _USE_LFN /* LFN configuration */ + WORD n, ne, is; + BYTE sn[12], *fn, sum; + WCHAR *lfn; + + + fn = dj->fn; lfn = dj->lfn; + mem_cpy(sn, fn, 12); + + if (_FS_RPATH && (sn[NS] & NS_DOT)) /* Cannot create dot entry */ + return FR_INVALID_NAME; + + if (sn[NS] & NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */ + fn[NS] = 0; dj->lfn = 0; /* Find only SFN */ + for (n = 1; n < 100; n++) { + gen_numname(fn, sn, lfn, n); /* Generate a numbered name */ + res = dir_find(dj); /* Check if the name collides with existing SFN */ + if (res != FR_OK) break; + } + if (n == 100) return FR_DENIED; /* Abort if too many collisions */ + if (res != FR_NO_FILE) return res; /* Abort if the result is other than 'not collided' */ + fn[NS] = sn[NS]; dj->lfn = lfn; + } + + if (sn[NS] & NS_LFN) { /* When LFN is to be created, reserve an SFN + LFN entries. */ + for (ne = 0; lfn[ne]; ne++) ; + ne = (ne + 25) / 13; + } else { /* Otherwise reserve only an SFN entry. */ + ne = 1; + } + + /* Reserve contiguous entries */ + res = dir_sdi(dj, 0); + if (res != FR_OK) return res; + n = is = 0; + do { + res = move_window(dj->fs, dj->sect); + if (res != FR_OK) break; + c = *dj->dir; /* Check the entry status */ + if (c == DDE || c == 0) { /* Is it a blank entry? */ + if (n == 0) is = dj->index; /* First index of the contiguous entry */ + if (++n == ne) break; /* A contiguous entry that required count is found */ + } else { + n = 0; /* Not a blank entry. Restart to search */ + } + res = dir_next(dj, 1); /* Next entry with table stretch */ + } while (res == FR_OK); + + if (res == FR_OK && ne > 1) { /* Initialize LFN entry if needed */ + res = dir_sdi(dj, is); + if (res == FR_OK) { + sum = sum_sfn(dj->fn); /* Sum of the SFN tied to the LFN */ + ne--; + do { /* Store LFN entries in bottom first */ + res = move_window(dj->fs, dj->sect); + if (res != FR_OK) break; + fit_lfn(dj->lfn, dj->dir, (BYTE)ne, sum); + dj->fs->wflag = 1; + res = dir_next(dj, 0); /* Next entry */ + } while (res == FR_OK && --ne); + } + } + +#else /* Non LFN configuration */ + res = dir_sdi(dj, 0); + if (res == FR_OK) { + do { /* Find a blank entry for the SFN */ + res = move_window(dj->fs, dj->sect); + if (res != FR_OK) break; + c = *dj->dir; + if (c == DDE || c == 0) break; /* Is it a blank entry? */ + res = dir_next(dj, 1); /* Next entry with table stretch */ + } while (res == FR_OK); + } +#endif + + if (res == FR_OK) { /* Initialize the SFN entry */ + res = move_window(dj->fs, dj->sect); + if (res == FR_OK) { + dir = dj->dir; + mem_set(dir, 0, SZ_DIR); /* Clean the entry */ + mem_cpy(dir, dj->fn, 11); /* Put SFN */ +#if _USE_LFN + dir[DIR_NTres] = *(dj->fn+NS) & (NS_BODY | NS_EXT); /* Put NT flag */ +#endif + dj->fs->wflag = 1; + } + } + + return res; +} +#endif /* !_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* Remove an object from the directory */ +/*-----------------------------------------------------------------------*/ +#if !_FS_READONLY && !_FS_MINIMIZE +static +FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */ + FATFS_DIR *dj /* Directory object pointing the entry to be removed */ +) +{ + FRESULT res; +#if _USE_LFN /* LFN configuration */ + WORD i; + + i = dj->index; /* SFN index */ + res = dir_sdi(dj, (WORD)((dj->lfn_idx == 0xFFFF) ? i : dj->lfn_idx)); /* Goto the SFN or top of the LFN entries */ + if (res == FR_OK) { + do { + res = move_window(dj->fs, dj->sect); + if (res != FR_OK) break; + *dj->dir = DDE; /* Mark the entry "deleted" */ + dj->fs->wflag = 1; + if (dj->index >= i) break; /* When reached SFN, all entries of the object has been deleted. */ + res = dir_next(dj, 0); /* Next entry */ + } while (res == FR_OK); + if (res == FR_NO_FILE) res = FR_INT_ERR; + } + +#else /* Non LFN configuration */ + res = dir_sdi(dj, dj->index); + if (res == FR_OK) { + res = move_window(dj->fs, dj->sect); + if (res == FR_OK) { + *dj->dir = DDE; /* Mark the entry "deleted" */ + dj->fs->wflag = 1; + } + } +#endif + + return res; +} +#endif /* !_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* Pick a segment and create the object name in directory form */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT create_name ( + FATFS_DIR *dj, /* Pointer to the directory object */ + const TCHAR **path /* Pointer to pointer to the segment in the path string */ +) +{ +#ifdef _EXCVT + static const BYTE excvt[] = _EXCVT; /* Upper conversion table for extended chars */ +#endif + +#if _USE_LFN /* LFN configuration */ + BYTE b, cf; + WCHAR w, *lfn; + UINT i, ni, si, di; + const TCHAR *p; + + /* Create LFN in Unicode */ + for (p = *path; *p == '/' || *p == '\\'; p++) ; /* Strip duplicated separator */ + lfn = dj->lfn; + si = di = 0; + for (;;) { + w = p[si++]; /* Get a character */ + if (w < ' ' || w == '/' || w == '\\') break; /* Break on end of segment */ + if (di >= _MAX_LFN) /* Reject too long name */ + return FR_INVALID_NAME; +#if !_LFN_UNICODE + w &= 0xFF; + if (IsDBCS1(w)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */ + b = (BYTE)p[si++]; /* Get 2nd byte */ + if (!IsDBCS2(b)) + return FR_INVALID_NAME; /* Reject invalid sequence */ + w = (w << 8) + b; /* Create a DBC */ + } + w = ff_convert(w, 1); /* Convert ANSI/OEM to Unicode */ + if (!w) return FR_INVALID_NAME; /* Reject invalid code */ +#endif + if (w < 0x80 && chk_chr("\"*:<>\?|\x7F", w)) /* Reject illegal chars for LFN */ + return FR_INVALID_NAME; + lfn[di++] = w; /* Store the Unicode char */ + } + *path = &p[si]; /* Return pointer to the next segment */ + cf = (w < ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */ +#if _FS_RPATH + if ((di == 1 && lfn[di-1] == '.') || /* Is this a dot entry? */ + (di == 2 && lfn[di-1] == '.' && lfn[di-2] == '.')) { + lfn[di] = 0; + for (i = 0; i < 11; i++) + dj->fn[i] = (i < di) ? '.' : ' '; + dj->fn[i] = cf | NS_DOT; /* This is a dot entry */ + return FR_OK; + } +#endif + while (di) { /* Strip trailing spaces and dots */ + w = lfn[di-1]; + if (w != ' ' && w != '.') break; + di--; + } + if (!di) return FR_INVALID_NAME; /* Reject nul string */ + + lfn[di] = 0; /* LFN is created */ + + /* Create SFN in directory form */ + mem_set(dj->fn, ' ', 11); + for (si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++) ; /* Strip leading spaces and dots */ + if (si) cf |= NS_LOSS | NS_LFN; + while (di && lfn[di - 1] != '.') di--; /* Find extension (di<=si: no extension) */ + + b = i = 0; ni = 8; + for (;;) { + w = lfn[si++]; /* Get an LFN char */ + if (!w) break; /* Break on end of the LFN */ + if (w == ' ' || (w == '.' && si != di)) { /* Remove spaces and dots */ + cf |= NS_LOSS | NS_LFN; continue; + } + + if (i >= ni || si == di) { /* Extension or end of SFN */ + if (ni == 11) { /* Long extension */ + cf |= NS_LOSS | NS_LFN; break; + } + if (si != di) cf |= NS_LOSS | NS_LFN; /* Out of 8.3 format */ + if (si > di) break; /* No extension */ + si = di; i = 8; ni = 11; /* Enter extension section */ + b <<= 2; continue; + } + + if (w >= 0x80) { /* Non ASCII char */ +#ifdef _EXCVT + w = ff_convert(w, 0); /* Unicode -> OEM code */ + if (w) w = excvt[w - 0x80]; /* Convert extended char to upper (SBCS) */ +#else + w = ff_convert(ff_wtoupper(w), 0); /* Upper converted Unicode -> OEM code */ +#endif + cf |= NS_LFN; /* Force create LFN entry */ + } + + if (_DF1S && w >= 0x100) { /* Double byte char (always false on SBCS cfg) */ + if (i >= ni - 1) { + cf |= NS_LOSS | NS_LFN; i = ni; continue; + } + dj->fn[i++] = (BYTE)(w >> 8); + } else { /* Single byte char */ + if (!w || chk_chr("+,;=[]", w)) { /* Replace illegal chars for SFN */ + w = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */ + } else { + if (IsUpper(w)) { /* ASCII large capital */ + b |= 2; + } else { + if (IsLower(w)) { /* ASCII small capital */ + b |= 1; w -= 0x20; + } + } + } + } + dj->fn[i++] = (BYTE)w; + } + + if (dj->fn[0] == DDE) dj->fn[0] = NDDE; /* If the first char collides with deleted mark, replace it with 0x05 */ + + if (ni == 8) b <<= 2; + if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) /* Create LFN entry when there are composite capitals */ + cf |= NS_LFN; + if (!(cf & NS_LFN)) { /* When LFN is in 8.3 format without extended char, NT flags are created */ + if ((b & 0x03) == 0x01) cf |= NS_EXT; /* NT flag (Extension has only small capital) */ + if ((b & 0x0C) == 0x04) cf |= NS_BODY; /* NT flag (Filename has only small capital) */ + } + + dj->fn[NS] = cf; /* SFN is created */ + + return FR_OK; + + +#else /* Non-LFN configuration */ + BYTE b, c, d, *sfn; + UINT ni, si, i; + const char *p; + + /* Create file name in directory form */ + for (p = *path; *p == '/' || *p == '\\'; p++) ; /* Strip duplicated separator */ + sfn = dj->fn; + mem_set(sfn, ' ', 11); + si = i = b = 0; ni = 8; +#if _FS_RPATH + if (p[si] == '.') { /* Is this a dot entry? */ + for (;;) { + c = (BYTE)p[si++]; + if (c != '.' || si >= 3) break; + sfn[i++] = c; + } + if (c != '/' && c != '\\' && c > ' ') return FR_INVALID_NAME; + *path = &p[si]; /* Return pointer to the next segment */ + sfn[NS] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT; /* Set last segment flag if end of path */ + return FR_OK; + } +#endif + for (;;) { + c = (BYTE)p[si++]; + if (c <= ' ' || c == '/' || c == '\\') break; /* Break on end of segment */ + if (c == '.' || i >= ni) { + if (ni != 8 || c != '.') return FR_INVALID_NAME; + i = 8; ni = 11; + b <<= 2; continue; + } + if (c >= 0x80) { /* Extended char? */ + b |= 3; /* Eliminate NT flag */ +#ifdef _EXCVT + c = excvt[c-0x80]; /* Upper conversion (SBCS) */ +#else +#if !_DF1S /* ASCII only cfg */ + return FR_INVALID_NAME; +#endif +#endif + } + if (IsDBCS1(c)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */ + d = (BYTE)p[si++]; /* Get 2nd byte */ + if (!IsDBCS2(d) || i >= ni - 1) /* Reject invalid DBC */ + return FR_INVALID_NAME; + sfn[i++] = c; + sfn[i++] = d; + } else { /* Single byte code */ + if (chk_chr("\"*+,:;<=>\?[]|\x7F", c)) /* Reject illegal chrs for SFN */ + return FR_INVALID_NAME; + if (IsUpper(c)) { /* ASCII large capital? */ + b |= 2; + } else { + if (IsLower(c)) { /* ASCII small capital? */ + b |= 1; c -= 0x20; + } + } + sfn[i++] = c; + } + } + *path = &p[si]; /* Return pointer to the next segment */ + c = (c <= ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */ + + if (!i) return FR_INVALID_NAME; /* Reject nul string */ + if (sfn[0] == DDE) sfn[0] = NDDE; /* When first char collides with DDE, replace it with 0x05 */ + + if (ni == 8) b <<= 2; + if ((b & 0x03) == 0x01) c |= NS_EXT; /* NT flag (Name extension has only small capital) */ + if ((b & 0x0C) == 0x04) c |= NS_BODY; /* NT flag (Name body has only small capital) */ + + sfn[NS] = c; /* Store NT flag, File name is created */ + + return FR_OK; +#endif +} + + + + +/*-----------------------------------------------------------------------*/ +/* Get file information from directory entry */ +/*-----------------------------------------------------------------------*/ +#if _FS_MINIMIZE <= 1 +static +void get_fileinfo ( /* No return code */ + FATFS_DIR *dj, /* Pointer to the directory object */ + FILINFO *fno /* Pointer to the file information to be filled */ +) +{ + UINT i; + BYTE nt, *dir; + TCHAR *p, c; + + + p = fno->fname; + if (dj->sect) { + dir = dj->dir; + nt = dir[DIR_NTres]; /* NT flag */ + for (i = 0; i < 8; i++) { /* Copy name body */ + c = dir[i]; + if (c == ' ') break; + if (c == NDDE) c = (TCHAR)DDE; + if (_USE_LFN && (nt & NS_BODY) && IsUpper(c)) c += 0x20; +#if _LFN_UNICODE + if (IsDBCS1(c) && i < 7 && IsDBCS2(dir[i+1])) + c = (c << 8) | dir[++i]; + c = ff_convert(c, 1); + if (!c) c = '?'; +#endif + *p++ = c; + } + if (dir[8] != ' ') { /* Copy name extension */ + *p++ = '.'; + for (i = 8; i < 11; i++) { + c = dir[i]; + if (c == ' ') break; + if (_USE_LFN && (nt & NS_EXT) && IsUpper(c)) c += 0x20; +#if _LFN_UNICODE + if (IsDBCS1(c) && i < 10 && IsDBCS2(dir[i+1])) + c = (c << 8) | dir[++i]; + c = ff_convert(c, 1); + if (!c) c = '?'; +#endif + *p++ = c; + } + } + fno->fattrib = dir[DIR_Attr]; /* Attribute */ + fno->fsize = LD_DWORD(dir+DIR_FileSize); /* Size */ + fno->fdate = LD_WORD(dir+DIR_WrtDate); /* Date */ + fno->ftime = LD_WORD(dir+DIR_WrtTime); /* Time */ + } + *p = 0; /* Terminate SFN str by a \0 */ + +#if _USE_LFN + if (fno->lfname && fno->lfsize) { + TCHAR *tp = fno->lfname; + WCHAR w, *lfn; + + i = 0; + if (dj->sect && dj->lfn_idx != 0xFFFF) {/* Get LFN if available */ + lfn = dj->lfn; + while ((w = *lfn++) != 0) { /* Get an LFN char */ +#if !_LFN_UNICODE + w = ff_convert(w, 0); /* Unicode -> OEM conversion */ + if (!w) { i = 0; break; } /* Could not convert, no LFN */ + if (_DF1S && w >= 0x100) /* Put 1st byte if it is a DBC (always false on SBCS cfg) */ + tp[i++] = (TCHAR)(w >> 8); +#endif + if (i >= fno->lfsize - 1) { i = 0; break; } /* Buffer overflow, no LFN */ + tp[i++] = (TCHAR)w; + } + } + tp[i] = 0; /* Terminate the LFN str by a \0 */ + } +#endif +} +#endif /* _FS_MINIMIZE <= 1 */ + + + + +/*-----------------------------------------------------------------------*/ +/* Follow a file path */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ + FATFS_DIR *dj, /* Directory object to return last directory and found object */ + const TCHAR *path /* Full-path string to find a file or directory */ +) +{ + FRESULT res; + BYTE *dir, ns; + + +#if _FS_RPATH + if (*path == '/' || *path == '\\') { /* There is a heading separator */ + path++; dj->sclust = 0; /* Strip it and start from the root dir */ + } else { /* No heading separator */ + dj->sclust = dj->fs->cdir; /* Start from the current dir */ + } +#else + if (*path == '/' || *path == '\\') /* Strip heading separator if exist */ + path++; + dj->sclust = 0; /* Start from the root dir */ +#endif + + if ((UINT)*path < ' ') { /* Nul path means the start directory itself */ + res = dir_sdi(dj, 0); + dj->dir = 0; + + } else { /* Follow path */ + for (;;) { + res = create_name(dj, &path); /* Get a segment */ + if (res != FR_OK) break; + res = dir_find(dj); /* Find it */ + ns = *(dj->fn+NS); + if (res != FR_OK) { /* Failed to find the object */ + if (res != FR_NO_FILE) break; /* Abort if any hard error occured */ + /* Object not found */ + if (_FS_RPATH && (ns & NS_DOT)) { /* If dot entry is not exit */ + dj->sclust = 0; dj->dir = 0; /* It is the root dir */ + res = FR_OK; + if (!(ns & NS_LAST)) continue; + } else { /* Could not find the object */ + if (!(ns & NS_LAST)) res = FR_NO_PATH; + } + break; + } + if (ns & NS_LAST) break; /* Last segment match. Function completed. */ + dir = dj->dir; /* There is next segment. Follow the sub directory */ + if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */ + res = FR_NO_PATH; break; + } + dj->sclust = LD_CLUST(dir); + } + } + + return res; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Load a sector and check if it is an FAT Volume Boot Record */ +/*-----------------------------------------------------------------------*/ + +static +BYTE check_fs ( /* 0:FAT-VBR, 1:Valid BR but not FAT, 2:Not a BR, 3:Disk error */ + FATFS *fs, /* File system object */ + DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */ +) +{ + if (disk_read(fs->drv, fs->win, sect, 1) != RES_OK) /* Load boot record */ + return 3; + if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55) /* Check record signature (always placed at offset 510 even if the sector size is >512) */ + return 2; + + if ((LD_DWORD(&fs->win[BS_FilSysType]) & 0xFFFFFF) == 0x544146) /* Check "FAT" string */ + return 0; + if ((LD_DWORD(&fs->win[BS_FilSysType32]) & 0xFFFFFF) == 0x544146) + return 0; + + return 1; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Check if the file system object is valid or not */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ + const TCHAR **path, /* Pointer to pointer to the path name (drive number) */ + FATFS **rfs, /* Pointer to pointer to the found file system object */ + BYTE chk_wp /* !=0: Check media write protection for write access */ +) +{ + BYTE fmt, b, pi, *tbl; + UINT vol; + DSTATUS stat; + DWORD bsect, fasize, tsect, sysect, nclst, szbfat; + WORD nrsv; + const TCHAR *p = *path; + FATFS *fs; + + /* Get logical drive number from the path name */ + vol = p[0] - '0'; /* Is there a drive number? */ + if (vol <= 9 && p[1] == ':') { /* Found a drive number, get and strip it */ + p += 2; *path = p; /* Return pointer to the path name */ + } else { /* No drive number is given */ +#if _FS_RPATH + vol = CurrVol; /* Use current drive */ +#else + vol = 0; /* Use drive 0 */ +#endif + } + + /* Check if the file system object is valid or not */ + if (vol >= _VOLUMES) /* Is the drive number valid? */ + return FR_INVALID_DRIVE; + *rfs = fs = FatFs[vol]; /* Return pointer to the corresponding file system object */ + if (!fs) return FR_NOT_ENABLED; /* Is the file system object available? */ + + ENTER_FF(fs); /* Lock file system */ + + if (fs->fs_type) { /* If the logical drive has been mounted */ + stat = disk_status(fs->drv); + if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized (has not been changed), */ + if (!_FS_READONLY && chk_wp && (stat & STA_PROTECT)) /* Check write protection if needed */ + return FR_WRITE_PROTECTED; + return FR_OK; /* The file system object is valid */ + } + } + + /* The file system object is not valid. */ + /* Following code attempts to mount the volume. (analyze BPB and initialize the fs object) */ + + fs->fs_type = 0; /* Clear the file system object */ + fs->drv = LD2PD(vol); /* Bind the logical drive and a physical drive */ + stat = disk_initialize(fs->drv); /* Initialize low level disk I/O layer */ + if (stat & STA_NOINIT) /* Check if the initialization succeeded */ + return FR_NOT_READY; /* Failed to initialize due to no media or hard error */ + if (!_FS_READONLY && chk_wp && (stat & STA_PROTECT)) /* Check disk write protection if needed */ + return FR_WRITE_PROTECTED; +#if _MAX_SS != 512 /* Get disk sector size (variable sector size cfg only) */ + if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &fs->ssize) != RES_OK) + return FR_DISK_ERR; +#endif + /* Search FAT partition on the drive. Supports only generic partitionings, FDISK and SFD. */ + fmt = check_fs(fs, bsect = 0); /* Load sector 0 and check if it is an FAT-VBR (in SFD) */ + if (LD2PT(vol) && !fmt) fmt = 1; /* Force non-SFD if the volume is forced partition */ + if (fmt == 1) { /* Not an FAT-VBR, the physical drive can be partitioned */ + /* Check the partition listed in the partition table */ + pi = LD2PT(vol); + if (pi) pi--; + tbl = &fs->win[MBR_Table + pi * SZ_PTE];/* Partition table */ + if (tbl[4]) { /* Is the partition existing? */ + bsect = LD_DWORD(&tbl[8]); /* Partition offset in LBA */ + fmt = check_fs(fs, bsect); /* Check the partition */ + } + } + if (fmt == 3) return FR_DISK_ERR; + if (fmt) return FR_NO_FILESYSTEM; /* No FAT volume is found */ + + /* An FAT volume is found. Following code initializes the file system object */ + + if (LD_WORD(fs->win+BPB_BytsPerSec) != SS(fs)) /* (BPB_BytsPerSec must be equal to the physical sector size) */ + return FR_NO_FILESYSTEM; + + fasize = LD_WORD(fs->win+BPB_FATSz16); /* Number of sectors per FAT */ + if (!fasize) fasize = LD_DWORD(fs->win+BPB_FATSz32); + fs->fsize = fasize; + + fs->n_fats = b = fs->win[BPB_NumFATs]; /* Number of FAT copies */ + if (b != 1 && b != 2) return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */ + fasize *= b; /* Number of sectors for FAT area */ + + fs->csize = b = fs->win[BPB_SecPerClus]; /* Number of sectors per cluster */ + if (!b || (b & (b - 1))) return FR_NO_FILESYSTEM; /* (Must be power of 2) */ + + fs->n_rootdir = LD_WORD(fs->win+BPB_RootEntCnt); /* Number of root directory entries */ + if (fs->n_rootdir % (SS(fs) / SZ_DIR)) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be sector aligned) */ + + tsect = LD_WORD(fs->win+BPB_TotSec16); /* Number of sectors on the volume */ + if (!tsect) tsect = LD_DWORD(fs->win+BPB_TotSec32); + + nrsv = LD_WORD(fs->win+BPB_RsvdSecCnt); /* Number of reserved sectors */ + if (!nrsv) return FR_NO_FILESYSTEM; /* (BPB_RsvdSecCnt must not be 0) */ + + /* Determine the FAT sub type */ + sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZ_DIR); /* RSV+FAT+FATFS_DIR */ + if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ + nclst = (tsect - sysect) / fs->csize; /* Number of clusters */ + if (!nclst) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ + fmt = FS_FAT12; + if (nclst >= MIN_FAT16) fmt = FS_FAT16; + if (nclst >= MIN_FAT32) fmt = FS_FAT32; + + /* Boundaries and Limits */ + fs->n_fatent = nclst + 2; /* Number of FAT entries */ + fs->database = bsect + sysect; /* Data start sector */ + fs->fatbase = bsect + nrsv; /* FAT start sector */ + if (fmt == FS_FAT32) { + if (fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */ + fs->dirbase = LD_DWORD(fs->win+BPB_RootClus); /* Root directory start cluster */ + szbfat = fs->n_fatent * 4; /* (Required FAT size) */ + } else { + if (!fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */ + fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */ + szbfat = (fmt == FS_FAT16) ? /* (Required FAT size) */ + fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1); + } + if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) /* (BPB_FATSz must not be less than required) */ + return FR_NO_FILESYSTEM; + +#if !_FS_READONLY + /* Initialize cluster allocation information */ + fs->free_clust = 0xFFFFFFFF; + fs->last_clust = 0; + + /* Get fsinfo if available */ + if (fmt == FS_FAT32) { + fs->fsi_flag = 0; + fs->fsi_sector = bsect + LD_WORD(fs->win+BPB_FSInfo); + if (disk_read(fs->drv, fs->win, fs->fsi_sector, 1) == RES_OK && + LD_WORD(fs->win+BS_55AA) == 0xAA55 && + LD_DWORD(fs->win+FSI_LeadSig) == 0x41615252 && + LD_DWORD(fs->win+FSI_StrucSig) == 0x61417272) { + fs->last_clust = LD_DWORD(fs->win+FSI_Nxt_Free); + fs->free_clust = LD_DWORD(fs->win+FSI_Free_Count); + } + } +#endif + fs->fs_type = fmt; /* FAT sub-type */ + fs->id = ++Fsid; /* File system mount ID */ + fs->winsect = 0; /* Invalidate sector cache */ + fs->wflag = 0; +#if _FS_RPATH + fs->cdir = 0; /* Current directory (root dir) */ +#endif +#if _FS_SHARE /* Clear file lock semaphores */ + clear_lock(fs); +#endif + + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Check if the file/dir object is valid or not */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */ + FATFS *fs, /* Pointer to the file system object */ + WORD id /* Member id of the target object to be checked */ +) +{ + if (!fs || !fs->fs_type || fs->id != id) + return FR_INVALID_OBJECT; + + ENTER_FF(fs); /* Lock file system */ + + if (disk_status(fs->drv) & STA_NOINIT) + return FR_NOT_READY; + + return FR_OK; +} + + + + +/*-------------------------------------------------------------------------- + + Public Functions + +--------------------------------------------------------------------------*/ + + + +/*-----------------------------------------------------------------------*/ +/* Mount/Unmount a Logical Drive */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_mount ( + BYTE vol, /* Logical drive number to be mounted/unmounted */ + FATFS *fs /* Pointer to new file system object (NULL for unmount)*/ +) +{ + FATFS *rfs; + + + if (vol >= _VOLUMES) /* Check if the drive number is valid */ + return FR_INVALID_DRIVE; + rfs = FatFs[vol]; /* Get current fs object */ + + if (rfs) { +#if _FS_SHARE + clear_lock(rfs); +#endif +#if _FS_REENTRANT /* Discard sync object of the current volume */ + if (!ff_del_syncobj(rfs->sobj)) return FR_INT_ERR; +#endif + rfs->fs_type = 0; /* Clear old fs object */ + } + + if (fs) { + fs->fs_type = 0; /* Clear new fs object */ +#if _FS_REENTRANT /* Create sync object for the new volume */ + if (!ff_cre_syncobj(vol, &fs->sobj)) return FR_INT_ERR; +#endif + } + FatFs[vol] = fs; /* Register new fs object */ + + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Open or Create a File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_open ( + FIL *fp, /* Pointer to the blank file object */ + const TCHAR *path, /* Pointer to the file name */ + BYTE mode /* Access mode and file open mode flags */ +) +{ + FRESULT res; + FATFS_DIR dj; + BYTE *dir; + DEF_NAMEBUF; + + + fp->fs = 0; /* Clear file object */ + +#if !_FS_READONLY + mode &= FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW; + res = chk_mounted(&path, &dj.fs, (BYTE)(mode & ~FA_READ)); +#else + mode &= FA_READ; + res = chk_mounted(&path, &dj.fs, 0); +#endif + INIT_BUF(dj); + if (res == FR_OK) + res = follow_path(&dj, path); /* Follow the file path */ + dir = dj.dir; + +#if !_FS_READONLY /* R/W configuration */ + if (res == FR_OK) { + if (!dir) /* Current dir itself */ + res = FR_INVALID_NAME; +#if _FS_SHARE + else + res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0); +#endif + } + /* Create or Open a file */ + if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) { + DWORD dw, cl; + + if (res != FR_OK) { /* No file, create new */ + if (res == FR_NO_FILE) /* There is no file to open, create a new entry */ +#if _FS_SHARE + res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES; +#else + res = dir_register(&dj); +#endif + mode |= FA_CREATE_ALWAYS; /* File is created */ + dir = dj.dir; /* New entry */ + } + else { /* Any object is already existing */ + if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or FATFS_DIR) */ + res = FR_DENIED; + } else { + if (mode & FA_CREATE_NEW) /* Cannot create as new file */ + res = FR_EXIST; + } + } + if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate it if overwrite mode */ + dw = get_fattime(); /* Created time */ + ST_DWORD(dir+DIR_CrtTime, dw); + dir[DIR_Attr] = 0; /* Reset attribute */ + ST_DWORD(dir+DIR_FileSize, 0); /* size = 0 */ + cl = LD_CLUST(dir); /* Get start cluster */ + ST_CLUST(dir, 0); /* cluster = 0 */ + dj.fs->wflag = 1; + if (cl) { /* Remove the cluster chain if exist */ + dw = dj.fs->winsect; + res = remove_chain(dj.fs, cl); + if (res == FR_OK) { + dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */ + res = move_window(dj.fs, dw); + } + } + } + } + else { /* Open an existing file */ + if (res == FR_OK) { /* Follow succeeded */ + if (dir[DIR_Attr] & AM_DIR) { /* It is a directory */ + res = FR_NO_FILE; + } else { + if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */ + res = FR_DENIED; + } + } + } + if (res == FR_OK) { + if (mode & FA_CREATE_ALWAYS) /* Set file change flag if created or overwritten */ + mode |= FA__WRITTEN; + fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */ + fp->dir_ptr = dir; +#if _FS_SHARE + fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0); + if (!fp->lockid) res = FR_INT_ERR; +#endif + } + +#else /* R/O configuration */ + if (res == FR_OK) { /* Follow succeeded */ + if (!dir) { /* Current dir itself */ + res = FR_INVALID_NAME; + } else { + if (dir[DIR_Attr] & AM_DIR) /* It is a directory */ + res = FR_NO_FILE; + } + } +#endif + FREE_BUF(); + + if (res == FR_OK) { + fp->flag = mode; /* File access mode */ + fp->sclust = LD_CLUST(dir); /* File start cluster */ + fp->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */ + fp->fptr = 0; /* File pointer */ + fp->dsect = 0; +#if _USE_FASTSEEK + fp->cltbl = 0; /* Normal seek mode */ +#endif + fp->fs = dj.fs; fp->id = dj.fs->id; /* Validate file object */ + } + + LEAVE_FF(dj.fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Read File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_read ( + FIL *fp, /* Pointer to the file object */ + void *buff, /* Pointer to data buffer */ + UINT btr, /* Number of bytes to read */ + UINT *br /* Pointer to number of bytes read */ +) +{ + FRESULT res; + DWORD clst, sect, remain; + UINT rcnt, cc; + BYTE csect, *rbuff = (BYTE*)buff; + + + *br = 0; /* Initialize byte counter */ + + res = validate(fp->fs, fp->id); /* Check validity */ + if (res != FR_OK) LEAVE_FF(fp->fs, res); + if (fp->flag & FA__ERROR) /* Aborted file? */ + LEAVE_FF(fp->fs, FR_INT_ERR); + if (!(fp->flag & FA_READ)) /* Check access mode */ + LEAVE_FF(fp->fs, FR_DENIED); + remain = fp->fsize - fp->fptr; + if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ + + for ( ; btr; /* Repeat until all data read */ + rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) { + if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ + csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ + if (!csect) { /* On the cluster boundary? */ + if (fp->fptr == 0) { /* On the top of the file? */ + clst = fp->sclust; /* Follow from the origin */ + } else { /* Middle or end of the file */ +#if _USE_FASTSEEK + if (fp->cltbl) + clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + else +#endif + clst = get_fat(fp->fs, fp->clust); /* Follow cluster chain on the FAT */ + } + if (clst < 2) ABORT(fp->fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + } + sect = clust2sect(fp->fs, fp->clust); /* Get current sector */ + if (!sect) ABORT(fp->fs, FR_INT_ERR); + sect += csect; + cc = btr / SS(fp->fs); /* When remaining bytes >= sector size, */ + if (cc) { /* Read maximum contiguous sectors directly */ + if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ + cc = fp->fs->csize - csect; + if (disk_read(fp->fs->drv, rbuff, sect, (BYTE)cc) != RES_OK) + ABORT(fp->fs, FR_DISK_ERR); +#if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ +#if _FS_TINY + if (fp->fs->wflag && fp->fs->winsect - sect < cc) + mem_cpy(rbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), fp->fs->win, SS(fp->fs)); +#else + if ((fp->flag & FA__DIRTY) && fp->dsect - sect < cc) + mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs)); +#endif +#endif + rcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ + continue; + } +#if !_FS_TINY + if (fp->dsect != sect) { /* Load data sector if not in cache */ +#if !_FS_READONLY + if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) + ABORT(fp->fs, FR_DISK_ERR); + fp->flag &= ~FA__DIRTY; + } +#endif + if (disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) /* Fill sector cache */ + ABORT(fp->fs, FR_DISK_ERR); + } +#endif + fp->dsect = sect; + } + rcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */ + if (rcnt > btr) rcnt = btr; +#if _FS_TINY + if (move_window(fp->fs, fp->dsect)) /* Move sector window */ + ABORT(fp->fs, FR_DISK_ERR); + mem_cpy(rbuff, &fp->fs->win[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */ +#else + mem_cpy(rbuff, &fp->buf[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */ +#endif + } + + LEAVE_FF(fp->fs, FR_OK); +} + + + + +#if !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Write File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_write ( + FIL *fp, /* Pointer to the file object */ + const void *buff, /* Pointer to the data to be written */ + UINT btw, /* Number of bytes to write */ + UINT *bw /* Pointer to number of bytes written */ +) +{ + FRESULT res; + DWORD clst, sect; + UINT wcnt, cc; + const BYTE *wbuff = (const BYTE*)buff; + BYTE csect; + + + *bw = 0; /* Initialize byte counter */ + + res = validate(fp->fs, fp->id); /* Check validity */ + if (res != FR_OK) LEAVE_FF(fp->fs, res); + if (fp->flag & FA__ERROR) /* Aborted file? */ + LEAVE_FF(fp->fs, FR_INT_ERR); + if (!(fp->flag & FA_WRITE)) /* Check access mode */ + LEAVE_FF(fp->fs, FR_DENIED); + if ((DWORD)(fp->fsize + btw) < fp->fsize) btw = 0; /* File size cannot reach 4GB */ + + for ( ; btw; /* Repeat until all data written */ + wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) { + if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ + csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ + if (!csect) { /* On the cluster boundary? */ + if (fp->fptr == 0) { /* On the top of the file? */ + clst = fp->sclust; /* Follow from the origin */ + if (clst == 0) /* When no cluster is allocated, */ + fp->sclust = clst = create_chain(fp->fs, 0); /* Create a new cluster chain */ + } else { /* Middle or end of the file */ +#if _USE_FASTSEEK + if (fp->cltbl) + clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + else +#endif + clst = create_chain(fp->fs, fp->clust); /* Follow or stretch cluster chain on the FAT */ + } + if (clst == 0) break; /* Could not allocate a new cluster (disk full) */ + if (clst == 1) ABORT(fp->fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + } +#if _FS_TINY + if (fp->fs->winsect == fp->dsect && move_window(fp->fs, 0)) /* Write-back sector cache */ + ABORT(fp->fs, FR_DISK_ERR); +#else + if (fp->flag & FA__DIRTY) { /* Write-back sector cache */ + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) + ABORT(fp->fs, FR_DISK_ERR); + fp->flag &= ~FA__DIRTY; + } +#endif + sect = clust2sect(fp->fs, fp->clust); /* Get current sector */ + if (!sect) ABORT(fp->fs, FR_INT_ERR); + sect += csect; + cc = btw / SS(fp->fs); /* When remaining bytes >= sector size, */ + if (cc) { /* Write maximum contiguous sectors directly */ + if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ + cc = fp->fs->csize - csect; + if (disk_write(fp->fs->drv, wbuff, sect, (BYTE)cc) != RES_OK) + ABORT(fp->fs, FR_DISK_ERR); +#if _FS_TINY + if (fp->fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ + mem_cpy(fp->fs->win, wbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), SS(fp->fs)); + fp->fs->wflag = 0; + } +#else + if (fp->dsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ + mem_cpy(fp->buf, wbuff + ((fp->dsect - sect) * SS(fp->fs)), SS(fp->fs)); + fp->flag &= ~FA__DIRTY; + } +#endif + wcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ + continue; + } +#if _FS_TINY + if (fp->fptr >= fp->fsize) { /* Avoid silly cache filling at growing edge */ + if (move_window(fp->fs, 0)) ABORT(fp->fs, FR_DISK_ERR); + fp->fs->winsect = sect; + } +#else + if (fp->dsect != sect) { /* Fill sector cache with file data */ + if (fp->fptr < fp->fsize && + disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) + ABORT(fp->fs, FR_DISK_ERR); + } +#endif + fp->dsect = sect; + } + wcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */ + if (wcnt > btw) wcnt = btw; +#if _FS_TINY + if (move_window(fp->fs, fp->dsect)) /* Move sector window */ + ABORT(fp->fs, FR_DISK_ERR); + mem_cpy(&fp->fs->win[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */ + fp->fs->wflag = 1; +#else + mem_cpy(&fp->buf[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */ + fp->flag |= FA__DIRTY; +#endif + } + + if (fp->fptr > fp->fsize) fp->fsize = fp->fptr; /* Update file size if needed */ + fp->flag |= FA__WRITTEN; /* Set file change flag */ + + LEAVE_FF(fp->fs, FR_OK); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Synchronize the File Object */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_sync ( + FIL *fp /* Pointer to the file object */ +) +{ + FRESULT res; + DWORD tim; + BYTE *dir; + + + res = validate(fp->fs, fp->id); /* Check validity of the object */ + if (res == FR_OK) { + if (fp->flag & FA__WRITTEN) { /* Has the file been written? */ +#if !_FS_TINY /* Write-back dirty buffer */ + if (fp->flag & FA__DIRTY) { + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) + LEAVE_FF(fp->fs, FR_DISK_ERR); + fp->flag &= ~FA__DIRTY; + } +#endif + /* Update the directory entry */ + res = move_window(fp->fs, fp->dir_sect); + if (res == FR_OK) { + dir = fp->dir_ptr; + dir[DIR_Attr] |= AM_ARC; /* Set archive bit */ + ST_DWORD(dir+DIR_FileSize, fp->fsize); /* Update file size */ + ST_CLUST(dir, fp->sclust); /* Update start cluster */ + tim = get_fattime(); /* Update updated time */ + ST_DWORD(dir+DIR_WrtTime, tim); + fp->flag &= ~FA__WRITTEN; + fp->fs->wflag = 1; + res = sync(fp->fs); + } + } + } + + LEAVE_FF(fp->fs, res); +} + +#endif /* !_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* Close File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_close ( + FIL *fp /* Pointer to the file object to be closed */ +) +{ + FRESULT res; + +#if _FS_READONLY + FATFS *fs = fp->fs; + res = validate(fs, fp->id); + if (res == FR_OK) fp->fs = 0; /* Discard file object */ + LEAVE_FF(fs, res); + +#else + res = f_sync(fp); /* Flush cached data */ +#if _FS_SHARE + if (res == FR_OK) { /* Decrement open counter */ +#if _FS_REENTRANT + res = validate(fp->fs, fp->id); + if (res == FR_OK) { + res = dec_lock(fp->lockid); + unlock_fs(fp->fs, FR_OK); + } +#else + res = dec_lock(fp->lockid); +#endif + } +#endif + if (res == FR_OK) fp->fs = 0; /* Discard file object */ + return res; +#endif +} + + + + +/*-----------------------------------------------------------------------*/ +/* Current Drive/Directory Handlings */ +/*-----------------------------------------------------------------------*/ + +#if _FS_RPATH >= 1 + +FRESULT f_chdrive ( + BYTE drv /* Drive number */ +) +{ + if (drv >= _VOLUMES) return FR_INVALID_DRIVE; + + CurrVol = drv; + + return FR_OK; +} + + + +FRESULT f_chdir ( + const TCHAR *path /* Pointer to the directory path */ +) +{ + FRESULT res; + FATFS_DIR dj; + DEF_NAMEBUF; + + + res = chk_mounted(&path, &dj.fs, 0); + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the path */ + FREE_BUF(); + if (res == FR_OK) { /* Follow completed */ + if (!dj.dir) { + dj.fs->cdir = dj.sclust; /* Start directory itself */ + } else { + if (dj.dir[DIR_Attr] & AM_DIR) /* Reached to the directory */ + dj.fs->cdir = LD_CLUST(dj.dir); + else + res = FR_NO_PATH; /* Reached but a file */ + } + } + if (res == FR_NO_FILE) res = FR_NO_PATH; + } + + LEAVE_FF(dj.fs, res); +} + + +#if _FS_RPATH >= 2 +FRESULT f_getcwd ( + TCHAR *path, /* Pointer to the directory path */ + UINT sz_path /* Size of path */ +) +{ + FRESULT res; + FATFS_DIR dj; + UINT i, n; + DWORD ccl; + TCHAR *tp; + FILINFO fno; + DEF_NAMEBUF; + + + *path = 0; + res = chk_mounted((const TCHAR**)&path, &dj.fs, 0); /* Get current volume */ + if (res == FR_OK) { + INIT_BUF(dj); + i = sz_path; /* Bottom of buffer (dir stack base) */ + dj.sclust = dj.fs->cdir; /* Start to follow upper dir from current dir */ + while ((ccl = dj.sclust) != 0) { /* Repeat while current dir is a sub-dir */ + res = dir_sdi(&dj, 1); /* Get parent dir */ + if (res != FR_OK) break; + res = dir_read(&dj); + if (res != FR_OK) break; + dj.sclust = LD_CLUST(dj.dir); /* Goto parent dir */ + res = dir_sdi(&dj, 0); + if (res != FR_OK) break; + do { /* Find the entry links to the child dir */ + res = dir_read(&dj); + if (res != FR_OK) break; + if (ccl == LD_CLUST(dj.dir)) break; /* Found the entry */ + res = dir_next(&dj, 0); + } while (res == FR_OK); + if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */ + if (res != FR_OK) break; +#if _USE_LFN + fno.lfname = path; + fno.lfsize = i; +#endif + get_fileinfo(&dj, &fno); /* Get the dir name and push it to the buffer */ + tp = fno.fname; + if (_USE_LFN && *path) tp = path; + for (n = 0; tp[n]; n++) ; + if (i < n + 3) { + res = FR_NOT_ENOUGH_CORE; break; + } + while (n) path[--i] = tp[--n]; + path[--i] = '/'; + } + tp = path; + if (res == FR_OK) { + *tp++ = '0' + CurrVol; /* Put drive number */ + *tp++ = ':'; + if (i == sz_path) { /* Root-dir */ + *tp++ = '/'; + } else { /* Sub-dir */ + do /* Add stacked path str */ + *tp++ = path[i++]; + while (i < sz_path); + } + } + *tp = 0; + FREE_BUF(); + } + + LEAVE_FF(dj.fs, res); +} +#endif /* _FS_RPATH >= 2 */ +#endif /* _FS_RPATH >= 1 */ + + + +#if _FS_MINIMIZE <= 2 +/*-----------------------------------------------------------------------*/ +/* Seek File R/W Pointer */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_lseek ( + FIL *fp, /* Pointer to the file object */ + DWORD ofs /* File pointer from top of file */ +) +{ + FRESULT res; + + + res = validate(fp->fs, fp->id); /* Check validity of the object */ + if (res != FR_OK) LEAVE_FF(fp->fs, res); + if (fp->flag & FA__ERROR) /* Check abort flag */ + LEAVE_FF(fp->fs, FR_INT_ERR); + +#if _USE_FASTSEEK + if (fp->cltbl) { /* Fast seek */ + DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl; + + if (ofs == CREATE_LINKMAP) { /* Create CLMT */ + tbl = fp->cltbl; + tlen = *tbl++; ulen = 2; /* Given table size and required table size */ + cl = fp->sclust; /* Top of the chain */ + if (cl) { + do { + /* Get a fragment */ + tcl = cl; ncl = 0; ulen += 2; /* Top, length and used items */ + do { + pcl = cl; ncl++; + cl = get_fat(fp->fs, cl); + if (cl <= 1) ABORT(fp->fs, FR_INT_ERR); + if (cl == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + } while (cl == pcl + 1); + if (ulen <= tlen) { /* Store the length and top of the fragment */ + *tbl++ = ncl; *tbl++ = tcl; + } + } while (cl < fp->fs->n_fatent); /* Repeat until end of chain */ + } + *fp->cltbl = ulen; /* Number of items used */ + if (ulen <= tlen) + *tbl = 0; /* Terminate table */ + else + res = FR_NOT_ENOUGH_CORE; /* Given table size is smaller than required */ + + } else { /* Fast seek */ + if (ofs > fp->fsize) /* Clip offset at the file size */ + ofs = fp->fsize; + fp->fptr = ofs; /* Set file pointer */ + if (ofs) { + fp->clust = clmt_clust(fp, ofs - 1); + dsc = clust2sect(fp->fs, fp->clust); + if (!dsc) ABORT(fp->fs, FR_INT_ERR); + dsc += (ofs - 1) / SS(fp->fs) & (fp->fs->csize - 1); + if (fp->fptr % SS(fp->fs) && dsc != fp->dsect) { /* Refill sector cache if needed */ +#if !_FS_TINY +#if !_FS_READONLY + if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) + ABORT(fp->fs, FR_DISK_ERR); + fp->flag &= ~FA__DIRTY; + } +#endif + if (disk_read(fp->fs->drv, fp->buf, dsc, 1) != RES_OK) /* Load current sector */ + ABORT(fp->fs, FR_DISK_ERR); +#endif + fp->dsect = dsc; + } + } + } + } else +#endif + + /* Normal Seek */ + { + DWORD clst, bcs, nsect, ifptr; + + if (ofs > fp->fsize /* In read-only mode, clip offset with the file size */ +#if !_FS_READONLY + && !(fp->flag & FA_WRITE) +#endif + ) ofs = fp->fsize; + + ifptr = fp->fptr; + fp->fptr = nsect = 0; + if (ofs) { + bcs = (DWORD)fp->fs->csize * SS(fp->fs); /* Cluster size (byte) */ + if (ifptr > 0 && + (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */ + fp->fptr = (ifptr - 1) & ~(bcs - 1); /* start from the current cluster */ + ofs -= fp->fptr; + clst = fp->clust; + } else { /* When seek to back cluster, */ + clst = fp->sclust; /* start from the first cluster */ +#if !_FS_READONLY + if (clst == 0) { /* If no cluster chain, create a new chain */ + clst = create_chain(fp->fs, 0); + if (clst == 1) ABORT(fp->fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + fp->sclust = clst; + } +#endif + fp->clust = clst; + } + if (clst != 0) { + while (ofs > bcs) { /* Cluster following loop */ +#if !_FS_READONLY + if (fp->flag & FA_WRITE) { /* Check if in write mode or not */ + clst = create_chain(fp->fs, clst); /* Force stretch if in write mode */ + if (clst == 0) { /* When disk gets full, clip file size */ + ofs = bcs; break; + } + } else +#endif + clst = get_fat(fp->fs, clst); /* Follow cluster chain if not in write mode */ + if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + if (clst <= 1 || clst >= fp->fs->n_fatent) ABORT(fp->fs, FR_INT_ERR); + fp->clust = clst; + fp->fptr += bcs; + ofs -= bcs; + } + fp->fptr += ofs; + if (ofs % SS(fp->fs)) { + nsect = clust2sect(fp->fs, clst); /* Current sector */ + if (!nsect) ABORT(fp->fs, FR_INT_ERR); + nsect += ofs / SS(fp->fs); + } + } + } + if (fp->fptr % SS(fp->fs) && nsect != fp->dsect) { /* Fill sector cache if needed */ +#if !_FS_TINY +#if !_FS_READONLY + if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) + ABORT(fp->fs, FR_DISK_ERR); + fp->flag &= ~FA__DIRTY; + } +#endif + if (disk_read(fp->fs->drv, fp->buf, nsect, 1) != RES_OK) /* Fill sector cache */ + ABORT(fp->fs, FR_DISK_ERR); +#endif + fp->dsect = nsect; + } +#if !_FS_READONLY + if (fp->fptr > fp->fsize) { /* Set file change flag if the file size is extended */ + fp->fsize = fp->fptr; + fp->flag |= FA__WRITTEN; + } +#endif + } + + LEAVE_FF(fp->fs, res); +} + + + +#if _FS_MINIMIZE <= 1 +/*-----------------------------------------------------------------------*/ +/* Create a Directroy Object */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_opendir ( + FATFS_DIR *dj, /* Pointer to directory object to create */ + const TCHAR *path /* Pointer to the directory path */ +) +{ + FRESULT res; + DEF_NAMEBUF; + + + res = chk_mounted(&path, &dj->fs, 0); + if (res == FR_OK) { + INIT_BUF(*dj); + res = follow_path(dj, path); /* Follow the path to the directory */ + FREE_BUF(); + if (res == FR_OK) { /* Follow completed */ + if (dj->dir) { /* It is not the root dir */ + if (dj->dir[DIR_Attr] & AM_DIR) { /* The object is a directory */ + dj->sclust = LD_CLUST(dj->dir); + } else { /* The object is not a directory */ + res = FR_NO_PATH; + } + } + if (res == FR_OK) { + dj->id = dj->fs->id; + res = dir_sdi(dj, 0); /* Rewind dir */ + } + } + if (res == FR_NO_FILE) res = FR_NO_PATH; + } + + LEAVE_FF(dj->fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Read Directory Entry in Sequense */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_readdir ( + FATFS_DIR *dj, /* Pointer to the open directory object */ + FILINFO *fno /* Pointer to file information to return */ +) +{ + FRESULT res; + DEF_NAMEBUF; + + + res = validate(dj->fs, dj->id); /* Check validity of the object */ + if (res == FR_OK) { + if (!fno) { + res = dir_sdi(dj, 0); /* Rewind the directory object */ + } else { + INIT_BUF(*dj); + res = dir_read(dj); /* Read an directory item */ + if (res == FR_NO_FILE) { /* Reached end of dir */ + dj->sect = 0; + res = FR_OK; + } + if (res == FR_OK) { /* A valid entry is found */ + get_fileinfo(dj, fno); /* Get the object information */ + res = dir_next(dj, 0); /* Increment index for next */ + if (res == FR_NO_FILE) { + dj->sect = 0; + res = FR_OK; + } + } + FREE_BUF(); + } + } + + LEAVE_FF(dj->fs, res); +} + + + +#if _FS_MINIMIZE == 0 +/*-----------------------------------------------------------------------*/ +/* Get File Status */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_stat ( + const TCHAR *path, /* Pointer to the file path */ + FILINFO *fno /* Pointer to file information to return */ +) +{ + FRESULT res; + FATFS_DIR dj; + DEF_NAMEBUF; + + + res = chk_mounted(&path, &dj.fs, 0); + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK) { /* Follow completed */ + if (dj.dir) /* Found an object */ + get_fileinfo(&dj, fno); + else /* It is root dir */ + res = FR_INVALID_NAME; + } + FREE_BUF(); + } + + LEAVE_FF(dj.fs, res); +} + + + +#if !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Get Number of Free Clusters */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_getfree ( + const TCHAR *path, /* Pointer to the logical drive number (root dir) */ + DWORD *nclst, /* Pointer to the variable to return number of free clusters */ + FATFS **fatfs /* Pointer to pointer to corresponding file system object to return */ +) +{ + FRESULT res; + DWORD n, clst, sect, stat; + UINT i; + BYTE fat, *p; + + + /* Get drive number */ + res = chk_mounted(&path, fatfs, 0); + if (res == FR_OK) { + /* If free_clust is valid, return it without full cluster scan */ + if ((*fatfs)->free_clust <= (*fatfs)->n_fatent - 2) { + *nclst = (*fatfs)->free_clust; + } else { + /* Get number of free clusters */ + fat = (*fatfs)->fs_type; + n = 0; + if (fat == FS_FAT12) { + clst = 2; + do { + stat = get_fat(*fatfs, clst); + if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } + if (stat == 1) { res = FR_INT_ERR; break; } + if (stat == 0) n++; + } while (++clst < (*fatfs)->n_fatent); + } else { + clst = (*fatfs)->n_fatent; + sect = (*fatfs)->fatbase; + i = 0; p = 0; + do { + if (!i) { + res = move_window(*fatfs, sect++); + if (res != FR_OK) break; + p = (*fatfs)->win; + i = SS(*fatfs); + } + if (fat == FS_FAT16) { + if (LD_WORD(p) == 0) n++; + p += 2; i -= 2; + } else { + if ((LD_DWORD(p) & 0x0FFFFFFF) == 0) n++; + p += 4; i -= 4; + } + } while (--clst); + } + (*fatfs)->free_clust = n; + if (fat == FS_FAT32) (*fatfs)->fsi_flag = 1; + *nclst = n; + } + } + LEAVE_FF(*fatfs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Truncate File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_truncate ( + FIL *fp /* Pointer to the file object */ +) +{ + FRESULT res; + DWORD ncl; + + + res = validate(fp->fs, fp->id); /* Check validity of the object */ + if (res == FR_OK) { + if (fp->flag & FA__ERROR) { /* Check abort flag */ + res = FR_INT_ERR; + } else { + if (!(fp->flag & FA_WRITE)) /* Check access mode */ + res = FR_DENIED; + } + } + if (res == FR_OK) { + if (fp->fsize > fp->fptr) { + fp->fsize = fp->fptr; /* Set file size to current R/W point */ + fp->flag |= FA__WRITTEN; + if (fp->fptr == 0) { /* When set file size to zero, remove entire cluster chain */ + res = remove_chain(fp->fs, fp->sclust); + fp->sclust = 0; + } else { /* When truncate a part of the file, remove remaining clusters */ + ncl = get_fat(fp->fs, fp->clust); + res = FR_OK; + if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR; + if (ncl == 1) res = FR_INT_ERR; + if (res == FR_OK && ncl < fp->fs->n_fatent) { + res = put_fat(fp->fs, fp->clust, 0x0FFFFFFF); + if (res == FR_OK) res = remove_chain(fp->fs, ncl); + } + } + } + if (res != FR_OK) fp->flag |= FA__ERROR; + } + + LEAVE_FF(fp->fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Delete a File or Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_unlink ( + const TCHAR *path /* Pointer to the file or directory path */ +) +{ + FRESULT res; + FATFS_DIR dj, sdj; + BYTE *dir; + DWORD dclst; + DEF_NAMEBUF; + + + res = chk_mounted(&path, &dj.fs, 1); + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the file path */ + if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) + res = FR_INVALID_NAME; /* Cannot remove dot entry */ +#if _FS_SHARE + if (res == FR_OK) res = chk_lock(&dj, 2); /* Cannot remove open file */ +#endif + if (res == FR_OK) { /* The object is accessible */ + dir = dj.dir; + if (!dir) { + res = FR_INVALID_NAME; /* Cannot remove the start directory */ + } else { + if (dir[DIR_Attr] & AM_RDO) + res = FR_DENIED; /* Cannot remove R/O object */ + } + dclst = LD_CLUST(dir); + if (res == FR_OK && (dir[DIR_Attr] & AM_DIR)) { /* Is it a sub-dir? */ + if (dclst < 2) { + res = FR_INT_ERR; + } else { + mem_cpy(&sdj, &dj, sizeof(FATFS_DIR)); /* Check if the sub-dir is empty or not */ + sdj.sclust = dclst; + res = dir_sdi(&sdj, 2); /* Exclude dot entries */ + if (res == FR_OK) { + res = dir_read(&sdj); + if (res == FR_OK /* Not empty dir */ +#if _FS_RPATH + || dclst == sdj.fs->cdir /* Current dir */ +#endif + ) res = FR_DENIED; + if (res == FR_NO_FILE) res = FR_OK; /* Empty */ + } + } + } + if (res == FR_OK) { + res = dir_remove(&dj); /* Remove the directory entry */ + if (res == FR_OK) { + if (dclst) /* Remove the cluster chain if exist */ + res = remove_chain(dj.fs, dclst); + if (res == FR_OK) res = sync(dj.fs); + } + } + } + FREE_BUF(); + } + LEAVE_FF(dj.fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Create a Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_mkdir ( + const TCHAR *path /* Pointer to the directory path */ +) +{ + FRESULT res; + FATFS_DIR dj; + BYTE *dir, n; + DWORD dsc, dcl, pcl, tim = get_fattime(); + DEF_NAMEBUF; + + + res = chk_mounted(&path, &dj.fs, 1); + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK) res = FR_EXIST; /* Any object with same name is already existing */ + if (_FS_RPATH && res == FR_NO_FILE && (dj.fn[NS] & NS_DOT)) + res = FR_INVALID_NAME; + if (res == FR_NO_FILE) { /* Can create a new directory */ + dcl = create_chain(dj.fs, 0); /* Allocate a cluster for the new directory table */ + res = FR_OK; + if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster */ + if (dcl == 1) res = FR_INT_ERR; + if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR; + if (res == FR_OK) /* Flush FAT */ + res = move_window(dj.fs, 0); + if (res == FR_OK) { /* Initialize the new directory table */ + dsc = clust2sect(dj.fs, dcl); + dir = dj.fs->win; + mem_set(dir, 0, SS(dj.fs)); + mem_set(dir+DIR_Name, ' ', 8+3); /* Create "." entry */ + dir[DIR_Name] = '.'; + dir[DIR_Attr] = AM_DIR; + ST_DWORD(dir+DIR_WrtTime, tim); + ST_CLUST(dir, dcl); + mem_cpy(dir+SZ_DIR, dir, SZ_DIR); /* Create ".." entry */ + dir[33] = '.'; pcl = dj.sclust; + if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase) + pcl = 0; + ST_CLUST(dir+SZ_DIR, pcl); + for (n = dj.fs->csize; n; n--) { /* Write dot entries and clear following sectors */ + dj.fs->winsect = dsc++; + dj.fs->wflag = 1; + res = move_window(dj.fs, 0); + if (res != FR_OK) break; + mem_set(dir, 0, SS(dj.fs)); + } + } + if (res == FR_OK) res = dir_register(&dj); /* Register the object to the directoy */ + if (res != FR_OK) { + remove_chain(dj.fs, dcl); /* Could not register, remove cluster chain */ + } else { + dir = dj.dir; + dir[DIR_Attr] = AM_DIR; /* Attribute */ + ST_DWORD(dir+DIR_WrtTime, tim); /* Created time */ + ST_CLUST(dir, dcl); /* Table start cluster */ + dj.fs->wflag = 1; + res = sync(dj.fs); + } + } + FREE_BUF(); + } + + LEAVE_FF(dj.fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Change Attribute */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_chmod ( + const TCHAR *path, /* Pointer to the file path */ + BYTE value, /* Attribute bits */ + BYTE mask /* Attribute mask to change */ +) +{ + FRESULT res; + FATFS_DIR dj; + BYTE *dir; + DEF_NAMEBUF; + + + res = chk_mounted(&path, &dj.fs, 1); + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the file path */ + FREE_BUF(); + if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) + res = FR_INVALID_NAME; + if (res == FR_OK) { + dir = dj.dir; + if (!dir) { /* Is it a root directory? */ + res = FR_INVALID_NAME; + } else { /* File or sub directory */ + mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC; /* Valid attribute mask */ + dir[DIR_Attr] = (value & mask) | (dir[DIR_Attr] & (BYTE)~mask); /* Apply attribute change */ + dj.fs->wflag = 1; + res = sync(dj.fs); + } + } + } + + LEAVE_FF(dj.fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Change Timestamp */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_utime ( + const TCHAR *path, /* Pointer to the file/directory name */ + const FILINFO *fno /* Pointer to the time stamp to be set */ +) +{ + FRESULT res; + FATFS_DIR dj; + BYTE *dir; + DEF_NAMEBUF; + + + res = chk_mounted(&path, &dj.fs, 1); + if (res == FR_OK) { + INIT_BUF(dj); + res = follow_path(&dj, path); /* Follow the file path */ + FREE_BUF(); + if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) + res = FR_INVALID_NAME; + if (res == FR_OK) { + dir = dj.dir; + if (!dir) { /* Root directory */ + res = FR_INVALID_NAME; + } else { /* File or sub-directory */ + ST_WORD(dir+DIR_WrtTime, fno->ftime); + ST_WORD(dir+DIR_WrtDate, fno->fdate); + dj.fs->wflag = 1; + res = sync(dj.fs); + } + } + } + + LEAVE_FF(dj.fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Rename File/Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_rename ( + const TCHAR *path_old, /* Pointer to the old name */ + const TCHAR *path_new /* Pointer to the new name */ +) +{ + FRESULT res; + FATFS_DIR djo, djn; + BYTE buf[21], *dir; + DWORD dw; + DEF_NAMEBUF; + + + res = chk_mounted(&path_old, &djo.fs, 1); + if (res == FR_OK) { + djn.fs = djo.fs; + INIT_BUF(djo); + res = follow_path(&djo, path_old); /* Check old object */ + if (_FS_RPATH && res == FR_OK && (djo.fn[NS] & NS_DOT)) + res = FR_INVALID_NAME; +#if _FS_SHARE + if (res == FR_OK) res = chk_lock(&djo, 2); +#endif + if (res == FR_OK) { /* Old object is found */ + if (!djo.dir) { /* Is root dir? */ + res = FR_NO_FILE; + } else { + mem_cpy(buf, djo.dir+DIR_Attr, 21); /* Save the object information except for name */ + mem_cpy(&djn, &djo, sizeof(FATFS_DIR)); /* Check new object */ + res = follow_path(&djn, path_new); + if (res == FR_OK) res = FR_EXIST; /* The new object name is already existing */ + if (res == FR_NO_FILE) { /* Is it a valid path and no name collision? */ +/* Start critical section that any interruption or error can cause cross-link */ + res = dir_register(&djn); /* Register the new entry */ + if (res == FR_OK) { + dir = djn.dir; /* Copy object information except for name */ + mem_cpy(dir+13, buf+2, 19); + dir[DIR_Attr] = buf[0] | AM_ARC; + djo.fs->wflag = 1; + if (djo.sclust != djn.sclust && (dir[DIR_Attr] & AM_DIR)) { /* Update .. entry in the directory if needed */ + dw = clust2sect(djn.fs, LD_CLUST(dir)); + if (!dw) { + res = FR_INT_ERR; + } else { + res = move_window(djn.fs, dw); + dir = djn.fs->win+SZ_DIR; /* .. entry */ + if (res == FR_OK && dir[1] == '.') { + dw = (djn.fs->fs_type == FS_FAT32 && djn.sclust == djn.fs->dirbase) ? 0 : djn.sclust; + ST_CLUST(dir, dw); + djn.fs->wflag = 1; + } + } + } + if (res == FR_OK) { + res = dir_remove(&djo); /* Remove old entry */ + if (res == FR_OK) + res = sync(djo.fs); + } + } +/* End critical section */ + } + } + } + FREE_BUF(); + } + LEAVE_FF(djo.fs, res); +} + +#endif /* !_FS_READONLY */ +#endif /* _FS_MINIMIZE == 0 */ +#endif /* _FS_MINIMIZE <= 1 */ +#endif /* _FS_MINIMIZE <= 2 */ + + + +/*-----------------------------------------------------------------------*/ +/* Forward data to the stream directly (available on only tiny cfg) */ +/*-----------------------------------------------------------------------*/ +#if _USE_FORWARD && _FS_TINY + +FRESULT f_forward ( + FIL *fp, /* Pointer to the file object */ + UINT (*func)(const BYTE*,UINT), /* Pointer to the streaming function */ + UINT btr, /* Number of bytes to forward */ + UINT *bf /* Pointer to number of bytes forwarded */ +) +{ + FRESULT res; + DWORD remain, clst, sect; + UINT rcnt; + BYTE csect; + + + *bf = 0; /* Initialize byte counter */ + + res = validate(fp->fs, fp->id); /* Check validity of the object */ + if (res != FR_OK) LEAVE_FF(fp->fs, res); + if (fp->flag & FA__ERROR) /* Check error flag */ + LEAVE_FF(fp->fs, FR_INT_ERR); + if (!(fp->flag & FA_READ)) /* Check access mode */ + LEAVE_FF(fp->fs, FR_DENIED); + + remain = fp->fsize - fp->fptr; + if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ + + for ( ; btr && (*func)(0, 0); /* Repeat until all data transferred or stream becomes busy */ + fp->fptr += rcnt, *bf += rcnt, btr -= rcnt) { + csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ + if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ + if (!csect) { /* On the cluster boundary? */ + clst = (fp->fptr == 0) ? /* On the top of the file? */ + fp->sclust : get_fat(fp->fs, fp->clust); + if (clst <= 1) ABORT(fp->fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + } + } + sect = clust2sect(fp->fs, fp->clust); /* Get current data sector */ + if (!sect) ABORT(fp->fs, FR_INT_ERR); + sect += csect; + if (move_window(fp->fs, sect)) /* Move sector window */ + ABORT(fp->fs, FR_DISK_ERR); + fp->dsect = sect; + rcnt = SS(fp->fs) - (WORD)(fp->fptr % SS(fp->fs)); /* Forward data from sector window */ + if (rcnt > btr) rcnt = btr; + rcnt = (*func)(&fp->fs->win[(WORD)fp->fptr % SS(fp->fs)], rcnt); + if (!rcnt) ABORT(fp->fs, FR_INT_ERR); + } + + LEAVE_FF(fp->fs, FR_OK); +} +#endif /* _USE_FORWARD */ + + + +#if _USE_MKFS && !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Create File System on the Drive */ +/*-----------------------------------------------------------------------*/ +#define N_ROOTDIR 512 /* Number of root dir entries for FAT12/16 */ +#define N_FATS 1 /* Number of FAT copies (1 or 2) */ + + +FRESULT f_mkfs ( + BYTE drv, /* Logical drive number */ + BYTE sfd, /* Partitioning rule 0:FDISK, 1:SFD */ + UINT au /* Allocation unit size [bytes] */ +) +{ + static const WORD vst[] = { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 0}; + static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512}; + BYTE fmt, md, sys, *tbl, pdrv, part; + DWORD n_clst, vs, n, wsect; + UINT i; + DWORD b_vol, b_fat, b_dir, b_data; /* LBA */ + DWORD n_vol, n_rsv, n_fat, n_dir; /* Size */ + FATFS *fs; + DSTATUS stat; + + + /* Check mounted drive and clear work area */ + if (drv >= _VOLUMES) return FR_INVALID_DRIVE; + if (sfd > 1) return FR_INVALID_PARAMETER; + if (au & (au - 1)) return FR_INVALID_PARAMETER; + fs = FatFs[drv]; + if (!fs) return FR_NOT_ENABLED; + fs->fs_type = 0; + pdrv = LD2PD(drv); /* Physical drive */ + part = LD2PT(drv); /* Partition (0:auto detect, 1-4:get from partition table)*/ + + /* Get disk statics */ + stat = disk_initialize(pdrv); + if (stat & STA_NOINIT) return FR_NOT_READY; + if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; +#if _MAX_SS != 512 /* Get disk sector size */ + if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS) + return FR_DISK_ERR; +#endif + if (_MULTI_PARTITION && part) { + /* Get partition information from partition table in the MBR */ + if (disk_read(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR; + if (LD_WORD(fs->win+BS_55AA) != 0xAA55) return FR_MKFS_ABORTED; + tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE]; + if (!tbl[4]) return FR_MKFS_ABORTED; /* No partition? */ + b_vol = LD_DWORD(tbl+8); /* Volume start sector */ + n_vol = LD_DWORD(tbl+12); /* Volume size */ + } else { + /* Create a partition in this function */ + if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128) + return FR_DISK_ERR; + b_vol = (sfd) ? 0 : 63; /* Volume start sector */ + n_vol -= b_vol; /* Volume size */ + } + + if (!au) { /* AU auto selection */ + vs = n_vol / (2000 / (SS(fs) / 512)); + for (i = 0; vs < vst[i]; i++) ; + au = cst[i]; + } + au /= SS(fs); /* Number of sectors per cluster */ + if (au == 0) au = 1; + if (au > 128) au = 128; + + /* Pre-compute number of clusters and FAT syb-type */ + n_clst = n_vol / au; + fmt = FS_FAT12; + if (n_clst >= MIN_FAT16) fmt = FS_FAT16; + if (n_clst >= MIN_FAT32) fmt = FS_FAT32; + + /* Determine offset and size of FAT structure */ + if (fmt == FS_FAT32) { + n_fat = ((n_clst * 4) + 8 + SS(fs) - 1) / SS(fs); + n_rsv = 32; + n_dir = 0; + } else { + n_fat = (fmt == FS_FAT12) ? (n_clst * 3 + 1) / 2 + 3 : (n_clst * 2) + 4; + n_fat = (n_fat + SS(fs) - 1) / SS(fs); + n_rsv = 1; + n_dir = (DWORD)N_ROOTDIR * SZ_DIR / SS(fs); + } + b_fat = b_vol + n_rsv; /* FAT area start sector */ + b_dir = b_fat + n_fat * N_FATS; /* Directory area start sector */ + b_data = b_dir + n_dir; /* Data area start sector */ + if (n_vol < b_data + au - b_vol) return FR_MKFS_ABORTED; /* Too small volume */ + + /* Align data start sector to erase block boundary (for flash memory media) */ + if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1; + n = (b_data + n - 1) & ~(n - 1); /* Next nearest erase block from current data start */ + n = (n - b_data) / N_FATS; + if (fmt == FS_FAT32) { /* FAT32: Move FAT offset */ + n_rsv += n; + b_fat += n; + } else { /* FAT12/16: Expand FAT size */ + n_fat += n; + } + + /* Determine number of clusters and final check of validity of the FAT sub-type */ + n_clst = (n_vol - n_rsv - n_fat * N_FATS - n_dir) / au; + if ( (fmt == FS_FAT16 && n_clst < MIN_FAT16) + || (fmt == FS_FAT32 && n_clst < MIN_FAT32)) + return FR_MKFS_ABORTED; + + switch (fmt) { /* Determine system ID for partition table */ + case FS_FAT12: sys = 0x01; break; + case FS_FAT16: sys = (n_vol < 0x10000) ? 0x04 : 0x06; break; + default: sys = 0x0C; + } + + if (_MULTI_PARTITION && part) { + /* Update system ID in the partition table */ + tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE]; + tbl[4] = sys; + if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR; + md = 0xF8; + } else { + if (sfd) { /* No patition table (SFD) */ + md = 0xF0; + } else { /* Create partition table (FDISK) */ + mem_set(fs->win, 0, SS(fs)); + tbl = fs->win+MBR_Table; /* Create partiton table for single partition in the drive */ + tbl[1] = 1; /* Partition start head */ + tbl[2] = 1; /* Partition start sector */ + tbl[3] = 0; /* Partition start cylinder */ + tbl[4] = sys; /* System type */ + tbl[5] = 254; /* Partition end head */ + n = (b_vol + n_vol) / 63 / 255; + tbl[6] = (BYTE)((n >> 2) | 63); /* Partiiton end sector */ + tbl[7] = (BYTE)n; /* End cylinder */ + ST_DWORD(tbl+8, 63); /* Partition start in LBA */ + ST_DWORD(tbl+12, n_vol); /* Partition size in LBA */ + ST_WORD(fs->win+BS_55AA, 0xAA55); /* MBR signature */ + if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) /* Write it to the MBR sector */ + return FR_DISK_ERR; + md = 0xF8; + } + } + + /* Create BPB in the VBR */ + tbl = fs->win; /* Clear sector */ + mem_set(tbl, 0, SS(fs)); + mem_cpy(tbl, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code, OEM name */ + i = SS(fs); /* Sector size */ + ST_WORD(tbl+BPB_BytsPerSec, i); + tbl[BPB_SecPerClus] = (BYTE)au; /* Sectors per cluster */ + ST_WORD(tbl+BPB_RsvdSecCnt, n_rsv); /* Reserved sectors */ + tbl[BPB_NumFATs] = N_FATS; /* Number of FATs */ + i = (fmt == FS_FAT32) ? 0 : N_ROOTDIR; /* Number of rootdir entries */ + ST_WORD(tbl+BPB_RootEntCnt, i); + if (n_vol < 0x10000) { /* Number of total sectors */ + ST_WORD(tbl+BPB_TotSec16, n_vol); + } else { + ST_DWORD(tbl+BPB_TotSec32, n_vol); + } + tbl[BPB_Media] = md; /* Media descriptor */ + ST_WORD(tbl+BPB_SecPerTrk, 63); /* Number of sectors per track */ + ST_WORD(tbl+BPB_NumHeads, 255); /* Number of heads */ + ST_DWORD(tbl+BPB_HiddSec, b_vol); /* Hidden sectors */ + n = get_fattime(); /* Use current time as VSN */ + if (fmt == FS_FAT32) { + ST_DWORD(tbl+BS_VolID32, n); /* VSN */ + ST_DWORD(tbl+BPB_FATSz32, n_fat); /* Number of sectors per FAT */ + ST_DWORD(tbl+BPB_RootClus, 2); /* Root directory start cluster (2) */ + ST_WORD(tbl+BPB_FSInfo, 1); /* FSInfo record offset (VBR+1) */ + ST_WORD(tbl+BPB_BkBootSec, 6); /* Backup boot record offset (VBR+6) */ + tbl[BS_DrvNum32] = 0x80; /* Drive number */ + tbl[BS_BootSig32] = 0x29; /* Extended boot signature */ + mem_cpy(tbl+BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */ + } else { + ST_DWORD(tbl+BS_VolID, n); /* VSN */ + ST_WORD(tbl+BPB_FATSz16, n_fat); /* Number of sectors per FAT */ + tbl[BS_DrvNum] = 0x80; /* Drive number */ + tbl[BS_BootSig] = 0x29; /* Extended boot signature */ + mem_cpy(tbl+BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */ + } + ST_WORD(tbl+BS_55AA, 0xAA55); /* Signature (Offset is fixed here regardless of sector size) */ + if (disk_write(pdrv, tbl, b_vol, 1) != RES_OK) /* Write it to the VBR sector */ + return FR_DISK_ERR; + if (fmt == FS_FAT32) /* Write backup VBR if needed (VBR+6) */ + disk_write(pdrv, tbl, b_vol + 6, 1); + + /* Initialize FAT area */ + wsect = b_fat; + for (i = 0; i < N_FATS; i++) { /* Initialize each FAT copy */ + mem_set(tbl, 0, SS(fs)); /* 1st sector of the FAT */ + n = md; /* Media descriptor byte */ + if (fmt != FS_FAT32) { + n |= (fmt == FS_FAT12) ? 0x00FFFF00 : 0xFFFFFF00; + ST_DWORD(tbl+0, n); /* Reserve cluster #0-1 (FAT12/16) */ + } else { + n |= 0xFFFFFF00; + ST_DWORD(tbl+0, n); /* Reserve cluster #0-1 (FAT32) */ + ST_DWORD(tbl+4, 0xFFFFFFFF); + ST_DWORD(tbl+8, 0x0FFFFFFF); /* Reserve cluster #2 for root dir */ + } + if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK) + return FR_DISK_ERR; + mem_set(tbl, 0, SS(fs)); /* Fill following FAT entries with zero */ + for (n = 1; n < n_fat; n++) { /* This loop may take a time on FAT32 volume due to many single sector writes */ + if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK) + return FR_DISK_ERR; + } + } + + /* Initialize root directory */ + i = (fmt == FS_FAT32) ? au : n_dir; + do { + if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK) + return FR_DISK_ERR; + } while (--i); + +#if _USE_ERASE /* Erase data area if needed */ + { + DWORD eb[2]; + + eb[0] = wsect; eb[1] = wsect + (n_clst - ((fmt == FS_FAT32) ? 1 : 0)) * au - 1; + disk_ioctl(pdrv, CTRL_ERASE_SECTOR, eb); + } +#endif + + /* Create FSInfo if needed */ + if (fmt == FS_FAT32) { + ST_DWORD(tbl+FSI_LeadSig, 0x41615252); + ST_DWORD(tbl+FSI_StrucSig, 0x61417272); + ST_DWORD(tbl+FSI_Free_Count, n_clst - 1); /* Number of free clusters */ + ST_DWORD(tbl+FSI_Nxt_Free, 2); /* Last allocated cluster# */ + ST_WORD(tbl+BS_55AA, 0xAA55); + disk_write(pdrv, tbl, b_vol + 1, 1); /* Write original (VBR+1) */ + disk_write(pdrv, tbl, b_vol + 7, 1); /* Write backup (VBR+7) */ + } + + return (disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR; +} + + +#if _MULTI_PARTITION == 2 +/*-----------------------------------------------------------------------*/ +/* Divide Physical Drive */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_fdisk ( + BYTE pdrv, /* Physical drive number */ + const DWORD szt[], /* Pointer to the size table for each partitions */ + void* work /* Pointer to the working buffer */ +) +{ + UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl; + BYTE s_hd, e_hd, *p, *buf = (BYTE*)work; + DSTATUS stat; + DWORD sz_disk, sz_part, s_part; + + + stat = disk_initialize(pdrv); + if (stat & STA_NOINIT) return FR_NOT_READY; + if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; + if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR; + + /* Determine CHS in the table regardless of the drive geometry */ + for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ; + if (n == 256) n--; + e_hd = n - 1; + sz_cyl = 63 * n; + tot_cyl = sz_disk / sz_cyl; + + /* Create partition table */ + mem_set(buf, 0, _MAX_SS); + p = buf + MBR_Table; b_cyl = 0; + for (i = 0; i < 4; i++, p += SZ_PTE) { + p_cyl = (szt[i] <= 100) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl; + if (!p_cyl) continue; + s_part = (DWORD)sz_cyl * b_cyl; + sz_part = (DWORD)sz_cyl * p_cyl; + if (i == 0) { /* Exclude first track of cylinder 0 */ + s_hd = 1; + s_part += 63; sz_part -= 63; + } else { + s_hd = 0; + } + e_cyl = b_cyl + p_cyl - 1; + if (e_cyl >= tot_cyl) return FR_INVALID_PARAMETER; + + /* Set partition table */ + p[1] = s_hd; /* Start head */ + p[2] = (BYTE)((b_cyl >> 2) + 1); /* Start sector */ + p[3] = (BYTE)b_cyl; /* Start cylinder */ + p[4] = 0x06; /* System type (temporary setting) */ + p[5] = e_hd; /* End head */ + p[6] = (BYTE)((e_cyl >> 2) + 63); /* End sector */ + p[7] = (BYTE)e_cyl; /* End cylinder */ + ST_DWORD(p + 8, s_part); /* Start sector in LBA */ + ST_DWORD(p + 12, sz_part); /* Partition size */ + + /* Next partition */ + b_cyl += p_cyl; + } + ST_WORD(p, 0xAA55); + + /* Write it to the MBR */ + return (disk_write(pdrv, buf, 0, 1) || disk_ioctl(pdrv, CTRL_SYNC, 0)) ? FR_DISK_ERR : FR_OK; +} + + +#endif /* _MULTI_PARTITION == 2 */ +#endif /* _USE_MKFS && !_FS_READONLY */ + + + + +#if _USE_STRFUNC +/*-----------------------------------------------------------------------*/ +/* Get a string from the file */ +/*-----------------------------------------------------------------------*/ +TCHAR* f_gets ( + TCHAR* buff, /* Pointer to the string buffer to read */ + int len, /* Size of string buffer (characters) */ + FIL* fil /* Pointer to the file object */ +) +{ + int n = 0; + TCHAR c, *p = buff; + BYTE s[2]; + UINT rc; + + + while (n < len - 1) { /* Read bytes until buffer gets filled */ + f_read(fil, s, 1, &rc); + if (rc != 1) break; /* Break on EOF or error */ + c = s[0]; +#if _LFN_UNICODE /* Read a character in UTF-8 encoding */ + if (c >= 0x80) { + if (c < 0xC0) continue; /* Skip stray trailer */ + if (c < 0xE0) { /* Two-byte sequense */ + f_read(fil, s, 1, &rc); + if (rc != 1) break; + c = ((c & 0x1F) << 6) | (s[0] & 0x3F); + if (c < 0x80) c = '?'; + } else { + if (c < 0xF0) { /* Three-byte sequense */ + f_read(fil, s, 2, &rc); + if (rc != 2) break; + c = (c << 12) | ((s[0] & 0x3F) << 6) | (s[1] & 0x3F); + if (c < 0x800) c = '?'; + } else { /* Reject four-byte sequense */ + c = '?'; + } + } + } +#endif +#if _USE_STRFUNC >= 2 + if (c == '\r') continue; /* Strip '\r' */ +#endif + *p++ = c; + n++; + if (c == '\n') break; /* Break on EOL */ + } + *p = 0; + return n ? buff : 0; /* When no data read (eof or error), return with error. */ +} + + + +#if !_FS_READONLY +#include <stdarg.h> +/*-----------------------------------------------------------------------*/ +/* Put a character to the file */ +/*-----------------------------------------------------------------------*/ +int f_putc ( + TCHAR c, /* A character to be output */ + FIL* fil /* Pointer to the file object */ +) +{ + UINT bw, btw; + BYTE s[3]; + + +#if _USE_STRFUNC >= 2 + if (c == '\n') f_putc ('\r', fil); /* LF -> CRLF conversion */ +#endif + +#if _LFN_UNICODE /* Write the character in UTF-8 encoding */ + if (c < 0x80) { /* 7-bit */ + s[0] = (BYTE)c; + btw = 1; + } else { + if (c < 0x800) { /* 11-bit */ + s[0] = (BYTE)(0xC0 | (c >> 6)); + s[1] = (BYTE)(0x80 | (c & 0x3F)); + btw = 2; + } else { /* 16-bit */ + s[0] = (BYTE)(0xE0 | (c >> 12)); + s[1] = (BYTE)(0x80 | ((c >> 6) & 0x3F)); + s[2] = (BYTE)(0x80 | (c & 0x3F)); + btw = 3; + } + } +#else /* Write the character without conversion */ + s[0] = (BYTE)c; + btw = 1; +#endif + f_write(fil, s, btw, &bw); /* Write the char to the file */ + return (bw == btw) ? 1 : EOF; /* Return the result */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* Put a string to the file */ +/*-----------------------------------------------------------------------*/ +int f_puts ( + const TCHAR* str, /* Pointer to the string to be output */ + FIL* fil /* Pointer to the file object */ +) +{ + int n; + + + for (n = 0; *str; str++, n++) { + if (f_putc(*str, fil) == EOF) return EOF; + } + return n; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Put a formatted string to the file */ +/*-----------------------------------------------------------------------*/ +int f_printf ( + FIL* fil, /* Pointer to the file object */ + const TCHAR* str, /* Pointer to the format string */ + ... /* Optional arguments... */ +) +{ + va_list arp; + BYTE f, r; + UINT i, j, w; + ULONG v; + TCHAR c, d, s[16], *p; + int res, chc, cc; + + + va_start(arp, str); + + for (cc = res = 0; cc != EOF; res += cc) { + c = *str++; + if (c == 0) break; /* End of string */ + if (c != '%') { /* Non escape character */ + cc = f_putc(c, fil); + if (cc != EOF) cc = 1; + continue; + } + w = f = 0; + c = *str++; + if (c == '0') { /* Flag: '0' padding */ + f = 1; c = *str++; + } else { + if (c == '-') { /* Flag: left justified */ + f = 2; c = *str++; + } + } + while (IsDigit(c)) { /* Precision */ + w = w * 10 + c - '0'; + c = *str++; + } + if (c == 'l' || c == 'L') { /* Prefix: Size is long int */ + f |= 4; c = *str++; + } + if (!c) break; + d = c; + if (IsLower(d)) d -= 0x20; + switch (d) { /* Type is... */ + case 'S' : /* String */ + p = va_arg(arp, TCHAR*); + for (j = 0; p[j]; j++) ; + chc = 0; + if (!(f & 2)) { + while (j++ < w) chc += (cc = f_putc(' ', fil)); + } + chc += (cc = f_puts(p, fil)); + while (j++ < w) chc += (cc = f_putc(' ', fil)); + if (cc != EOF) cc = chc; + continue; + case 'C' : /* Character */ + cc = f_putc((TCHAR)va_arg(arp, int), fil); continue; + case 'B' : /* Binary */ + r = 2; break; + case 'O' : /* Octal */ + r = 8; break; + case 'D' : /* Signed decimal */ + case 'U' : /* Unsigned decimal */ + r = 10; break; + case 'X' : /* Hexdecimal */ + r = 16; break; + default: /* Unknown type (passthrough) */ + cc = f_putc(c, fil); continue; + } + + /* Get an argument and put it in numeral */ + v = (f & 4) ? (ULONG)va_arg(arp, long) : ((d == 'D') ? (ULONG)(long)va_arg(arp, int) : (ULONG)va_arg(arp, unsigned int)); + if (d == 'D' && (v & 0x80000000)) { + v = 0 - v; + f |= 8; + } + i = 0; + do { + d = (TCHAR)(v % r); v /= r; + if (d > 9) d += (c == 'x') ? 0x27 : 0x07; + s[i++] = d + '0'; + } while (v && i < sizeof(s) / sizeof(s[0])); + if (f & 8) s[i++] = '-'; + j = i; d = (f & 1) ? '0' : ' '; + res = 0; + while (!(f & 2) && j++ < w) res += (cc = f_putc(d, fil)); + do res += (cc = f_putc(s[--i], fil)); while(i); + while (j++ < w) res += (cc = f_putc(' ', fil)); + if (cc != EOF) cc = res; + } + + va_end(arp); + return (cc == EOF) ? cc : res; +} + +#endif /* !_FS_READONLY */ +#endif /* _USE_STRFUNC */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FatFileSystem/ff.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,337 @@ +/*---------------------------------------------------------------------------/ +/ FatFs - FAT file system module include file R0.09 (C)ChaN, 2011 +/----------------------------------------------------------------------------/ +/ FatFs module is a generic FAT file system module for small embedded systems. +/ This is a free software that opened for education, research and commercial +/ developments under license policy of following trems. +/ +/ Copyright (C) 2011, ChaN, all right reserved. +/ +/ * The FatFs module is a free software and there is NO WARRANTY. +/ * No restriction on use. You can use, modify and redistribute it for +/ personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY. +/ * Redistributions of source code must retain the above copyright notice. +/ +/----------------------------------------------------------------------------*/ + +#ifndef _FATFS +#define _FATFS 6502 /* Revision ID */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "integer.h" /* Basic integer types */ +#include "ffconf.h" /* FatFs configuration options */ + +#if _FATFS != _FFCONF +#error Wrong configuration file (ffconf.h). +#endif + + + +/* Definitions of volume management */ + +#if _MULTI_PARTITION /* Multiple partition configuration */ +typedef struct { + BYTE pd; /* Physical drive number */ + BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */ +} PARTITION; +extern PARTITION VolToPart[]; /* Volume - Partition resolution table */ +#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */ +#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */ + +#else /* Single partition configuration */ +#define LD2PD(vol) (vol) /* Each logical drive is bound to the same physical drive number */ +#define LD2PT(vol) 0 /* Always mounts the 1st partition or in SFD */ + +#endif + + + +/* Type of path name strings on FatFs API */ + +#if _LFN_UNICODE /* Unicode string */ +#if !_USE_LFN +#error _LFN_UNICODE must be 0 in non-LFN cfg. +#endif +#ifndef _INC_TCHAR +typedef WCHAR TCHAR; +#define _T(x) L ## x +#define _TEXT(x) L ## x +#endif + +#else /* ANSI/OEM string */ +#ifndef _INC_TCHAR +typedef char TCHAR; +#define _T(x) x +#define _TEXT(x) x +#endif + +#endif + + + +/* File system object structure (FATFS) */ + +typedef struct { + BYTE fs_type; /* FAT sub-type (0:Not mounted) */ + BYTE drv; /* Physical drive number */ + BYTE csize; /* Sectors per cluster (1,2,4...128) */ + BYTE n_fats; /* Number of FAT copies (1,2) */ + BYTE wflag; /* win[] dirty flag (1:must be written back) */ + BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */ + WORD id; /* File system mount ID */ + WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ +#if _MAX_SS != 512 + WORD ssize; /* Bytes per sector (512, 1024, 2048 or 4096) */ +#endif +#if _FS_REENTRANT + _SYNC_t sobj; /* Identifier of sync object */ +#endif +#if !_FS_READONLY + DWORD last_clust; /* Last allocated cluster */ + DWORD free_clust; /* Number of free clusters */ + DWORD fsi_sector; /* fsinfo sector (FAT32) */ +#endif +#if _FS_RPATH + DWORD cdir; /* Current directory start cluster (0:root) */ +#endif + DWORD n_fatent; /* Number of FAT entries (= number of clusters + 2) */ + DWORD fsize; /* Sectors per FAT */ + DWORD fatbase; /* FAT start sector */ + DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */ + DWORD database; /* Data start sector */ + DWORD winsect; /* Current sector appearing in the win[] */ + BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and Data on tiny cfg) */ +} FATFS; + + + +/* File object structure (FIL) */ + +typedef struct { + FATFS* fs; /* Pointer to the owner file system object */ + WORD id; /* Owner file system mount ID */ + BYTE flag; /* File status flags */ + BYTE pad1; + DWORD fptr; /* File read/write pointer (0 on file open) */ + DWORD fsize; /* File size */ + DWORD sclust; /* File start cluster (0 when fsize==0) */ + DWORD clust; /* Current cluster */ + DWORD dsect; /* Current data sector */ +#if !_FS_READONLY + DWORD dir_sect; /* Sector containing the directory entry */ + BYTE* dir_ptr; /* Ponter to the directory entry in the window */ +#endif +#if _USE_FASTSEEK + DWORD* cltbl; /* Pointer to the cluster link map table (null on file open) */ +#endif +#if _FS_SHARE + UINT lockid; /* File lock ID (index of file semaphore table) */ +#endif +#if !_FS_TINY + BYTE buf[_MAX_SS]; /* File data read/write buffer */ +#endif +} FIL; + + + +/* Directory object structure (FATFS_DIR) */ + +typedef struct { + FATFS* fs; /* Pointer to the owner file system object */ + WORD id; /* Owner file system mount ID */ + WORD index; /* Current read/write index number */ + DWORD sclust; /* Table start cluster (0:Root dir) */ + DWORD clust; /* Current cluster */ + DWORD sect; /* Current sector */ + BYTE* dir; /* Pointer to the current SFN entry in the win[] */ + BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */ +#if _USE_LFN + WCHAR* lfn; /* Pointer to the LFN working buffer */ + WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */ +#endif +} FATFS_DIR; + + + +/* File status structure (FILINFO) */ + +typedef struct { + DWORD fsize; /* File size */ + WORD fdate; /* Last modified date */ + WORD ftime; /* Last modified time */ + BYTE fattrib; /* Attribute */ + TCHAR fname[13]; /* Short file name (8.3 format) */ +#if _USE_LFN + TCHAR* lfname; /* Pointer to the LFN buffer */ + UINT lfsize; /* Size of LFN buffer in TCHAR */ +#endif +} FILINFO; + + + +/* File function return code (FRESULT) */ + +typedef enum { + FR_OK = 0, /* (0) Succeeded */ + FR_DISK_ERR, /* (1) A hard error occured in the low level disk I/O layer */ + FR_INT_ERR, /* (2) Assertion failed */ + FR_NOT_READY, /* (3) The physical drive cannot work */ + FR_NO_FILE, /* (4) Could not find the file */ + FR_NO_PATH, /* (5) Could not find the path */ + FR_INVALID_NAME, /* (6) The path name format is invalid */ + FR_DENIED, /* (7) Acces denied due to prohibited access or directory full */ + FR_EXIST, /* (8) Acces denied due to prohibited access */ + FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ + FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ + FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ + FR_NOT_ENABLED, /* (12) The volume has no work area */ + FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ + FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */ + FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ + FR_LOCKED, /* (16) The operation is rejected according to the file shareing policy */ + FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ + FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */ + FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ +} FRESULT; + + + +/*--------------------------------------------------------------*/ +/* FatFs module application interface */ + +FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */ +FRESULT f_open (FIL*, const TCHAR*, BYTE); /* Open or create a file */ +FRESULT f_read (FIL*, void*, UINT, UINT*); /* Read data from a file */ +FRESULT f_lseek (FIL*, DWORD); /* Move file pointer of a file object */ +FRESULT f_close (FIL*); /* Close an open file object */ +FRESULT f_opendir (FATFS_DIR*, const TCHAR*); /* Open an existing directory */ +FRESULT f_readdir (FATFS_DIR*, FILINFO*); /* Read a directory item */ +FRESULT f_stat (const TCHAR*, FILINFO*); /* Get file status */ +FRESULT f_write (FIL*, const void*, UINT, UINT*); /* Write data to a file */ +FRESULT f_getfree (const TCHAR*, DWORD*, FATFS**); /* Get number of free clusters on the drive */ +FRESULT f_truncate (FIL*); /* Truncate file */ +FRESULT f_sync (FIL*); /* Flush cached data of a writing file */ +FRESULT f_unlink (const TCHAR*); /* Delete an existing file or directory */ +FRESULT f_mkdir (const TCHAR*); /* Create a new directory */ +FRESULT f_chmod (const TCHAR*, BYTE, BYTE); /* Change attriburte of the file/dir */ +FRESULT f_utime (const TCHAR*, const FILINFO*); /* Change timestamp of the file/dir */ +FRESULT f_rename (const TCHAR*, const TCHAR*); /* Rename/Move a file or directory */ +FRESULT f_chdrive (BYTE); /* Change current drive */ +FRESULT f_chdir (const TCHAR*); /* Change current directory */ +FRESULT f_getcwd (TCHAR*, UINT); /* Get current directory */ +FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*); /* Forward data to the stream */ +FRESULT f_mkfs (BYTE, BYTE, UINT); /* Create a file system on the drive */ +FRESULT f_fdisk (BYTE, const DWORD[], void*); /* Divide a physical drive into some partitions */ +int f_putc (TCHAR, FIL*); /* Put a character to the file */ +int f_puts (const TCHAR*, FIL*); /* Put a string to the file */ +int f_printf (FIL*, const TCHAR*, ...); /* Put a formatted string to the file */ +TCHAR* f_gets (TCHAR*, int, FIL*); /* Get a string from the file */ + +#define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0) +#define f_error(fp) (((fp)->flag & FA__ERROR) ? 1 : 0) +#define f_tell(fp) ((fp)->fptr) +#define f_size(fp) ((fp)->fsize) + +#ifndef EOF +#define EOF (-1) +#endif + + + + +/*--------------------------------------------------------------*/ +/* Additional user defined functions */ + +/* RTC function */ +#if !_FS_READONLY +DWORD get_fattime (void); +#endif + +/* Unicode support functions */ +#if _USE_LFN /* Unicode - OEM code conversion */ +WCHAR ff_convert (WCHAR, UINT); /* OEM-Unicode bidirectional conversion */ +WCHAR ff_wtoupper (WCHAR); /* Unicode upper-case conversion */ +#if _USE_LFN == 3 /* Memory functions */ +void* ff_memalloc (UINT); /* Allocate memory block */ +void ff_memfree (void*); /* Free memory block */ +#endif +#endif + +/* Sync functions */ +#if _FS_REENTRANT +int ff_cre_syncobj (BYTE, _SYNC_t*);/* Create a sync object */ +int ff_req_grant (_SYNC_t); /* Lock sync object */ +void ff_rel_grant (_SYNC_t); /* Unlock sync object */ +int ff_del_syncobj (_SYNC_t); /* Delete a sync object */ +#endif + + + + +/*--------------------------------------------------------------*/ +/* Flags and offset address */ + + +/* File access control and file status flags (FIL.flag) */ + +#define FA_READ 0x01 +#define FA_OPEN_EXISTING 0x00 +#define FA__ERROR 0x80 + +#if !_FS_READONLY +#define FA_WRITE 0x02 +#define FA_CREATE_NEW 0x04 +#define FA_CREATE_ALWAYS 0x08 +#define FA_OPEN_ALWAYS 0x10 +#define FA__WRITTEN 0x20 +#define FA__DIRTY 0x40 +#endif + + +/* FAT sub type (FATFS.fs_type) */ + +#define FS_FAT12 1 +#define FS_FAT16 2 +#define FS_FAT32 3 + + +/* File attribute bits for directory entry */ + +#define AM_RDO 0x01 /* Read only */ +#define AM_HID 0x02 /* Hidden */ +#define AM_SYS 0x04 /* System */ +#define AM_VOL 0x08 /* Volume label */ +#define AM_LFN 0x0F /* LFN entry */ +#define AM_DIR 0x10 /* Directory */ +#define AM_ARC 0x20 /* Archive */ +#define AM_MASK 0x3F /* Mask of defined bits */ + + +/* Fast seek feature */ +#define CREATE_LINKMAP 0xFFFFFFFF + + + +/*--------------------------------*/ +/* Multi-byte word access macros */ + +#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */ +#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr)) +#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr)) +#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val) +#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val) +#else /* Use byte-by-byte access to the FAT structure */ +#define LD_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr)) +#define LD_DWORD(ptr) (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr)) +#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8) +#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _FATFS */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FatFileSystem/ffconf.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,190 @@ +/*---------------------------------------------------------------------------/ +/ FatFs - FAT file system module configuration file R0.09 (C)ChaN, 2011 +/----------------------------------------------------------------------------/ +/ +/ CAUTION! Do not forget to make clean the project after any changes to +/ the configuration options. +/ +/----------------------------------------------------------------------------*/ +#ifndef _FFCONF +#define _FFCONF 6502 /* Revision ID */ + + +/*---------------------------------------------------------------------------/ +/ Functions and Buffer Configurations +/----------------------------------------------------------------------------*/ + +#define _FS_TINY 0 /* 0:Normal or 1:Tiny */ +/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system +/ object instead of the sector buffer in the individual file object for file +/ data transfer. This reduces memory consumption 512 bytes each file object. */ + + +#define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */ +/* Setting _FS_READONLY to 1 defines read only configuration. This removes +/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename, +/ f_truncate and useless f_getfree. */ + + +#define _FS_MINIMIZE 0 /* 0 to 3 */ +/* The _FS_MINIMIZE option defines minimization level to remove some functions. +/ +/ 0: Full function. +/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename +/ are removed. +/ 2: f_opendir and f_readdir are removed in addition to 1. +/ 3: f_lseek is removed in addition to 2. */ + + +#define _USE_STRFUNC 0 /* 0:Disable or 1-2:Enable */ +/* To enable string functions, set _USE_STRFUNC to 1 or 2. */ + + +#define _USE_MKFS 1 /* 0:Disable or 1:Enable */ +/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */ + + +#define _USE_FORWARD 0 /* 0:Disable or 1:Enable */ +/* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */ + + +#define _USE_FASTSEEK 0 /* 0:Disable or 1:Enable */ +/* To enable fast seek feature, set _USE_FASTSEEK to 1. */ + + + +/*---------------------------------------------------------------------------/ +/ Locale and Namespace Configurations +/----------------------------------------------------------------------------*/ + +#define _CODE_PAGE 858 +/* The _CODE_PAGE specifies the OEM code page to be used on the target system. +/ Incorrect setting of the code page can cause a file open failure. +/ +/ 932 - Japanese Shift-JIS (DBCS, OEM, Windows) +/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows) +/ 949 - Korean (DBCS, OEM, Windows) +/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows) +/ 1250 - Central Europe (Windows) +/ 1251 - Cyrillic (Windows) +/ 1252 - Latin 1 (Windows) +/ 1253 - Greek (Windows) +/ 1254 - Turkish (Windows) +/ 1255 - Hebrew (Windows) +/ 1256 - Arabic (Windows) +/ 1257 - Baltic (Windows) +/ 1258 - Vietnam (OEM, Windows) +/ 437 - U.S. (OEM) +/ 720 - Arabic (OEM) +/ 737 - Greek (OEM) +/ 775 - Baltic (OEM) +/ 850 - Multilingual Latin 1 (OEM) +/ 858 - Multilingual Latin 1 + Euro (OEM) +/ 852 - Latin 2 (OEM) +/ 855 - Cyrillic (OEM) +/ 866 - Russian (OEM) +/ 857 - Turkish (OEM) +/ 862 - Hebrew (OEM) +/ 874 - Thai (OEM, Windows) +/ 1 - ASCII only (Valid for non LFN cfg.) +*/ + + +#define _USE_LFN 1 /* 0 to 3 */ +#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */ +/* The _USE_LFN option switches the LFN support. +/ +/ 0: Disable LFN feature. _MAX_LFN and _LFN_UNICODE have no effect. +/ 1: Enable LFN with static working buffer on the BSS. Always NOT reentrant. +/ 2: Enable LFN with dynamic working buffer on the STACK. +/ 3: Enable LFN with dynamic working buffer on the HEAP. +/ +/ The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. To enable LFN, +/ Unicode handling functions ff_convert() and ff_wtoupper() must be added +/ to the project. When enable to use heap, memory control functions +/ ff_memalloc() and ff_memfree() must be added to the project. */ + + +#define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */ +/* To switch the character code set on FatFs API to Unicode, +/ enable LFN feature and set _LFN_UNICODE to 1. */ + + +#define _FS_RPATH 0 /* 0 to 2 */ +/* The _FS_RPATH option configures relative path feature. +/ +/ 0: Disable relative path feature and remove related functions. +/ 1: Enable relative path. f_chdrive() and f_chdir() are available. +/ 2: f_getcwd() is available in addition to 1. +/ +/ Note that output of the f_readdir fnction is affected by this option. */ + + + +/*---------------------------------------------------------------------------/ +/ Physical Drive Configurations +/----------------------------------------------------------------------------*/ + +#define _VOLUMES 4 +/* Number of volumes (logical drives) to be used. */ + + +#define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */ +/* Maximum sector size to be handled. +/ Always set 512 for memory card and hard disk but a larger value may be +/ required for on-board flash memory, floppy disk and optical disk. +/ When _MAX_SS is larger than 512, it configures FatFs to variable sector size +/ and GET_SECTOR_SIZE command must be implememted to the disk_ioctl function. */ + + +#define _MULTI_PARTITION 0 /* 0:Single partition, 1/2:Enable multiple partition */ +/* When set to 0, each volume is bound to the same physical drive number and +/ it can mount only first primaly partition. When it is set to 1, each volume +/ is tied to the partitions listed in VolToPart[]. */ + + +#define _USE_ERASE 0 /* 0:Disable or 1:Enable */ +/* To enable sector erase feature, set _USE_ERASE to 1. CTRL_ERASE_SECTOR command +/ should be added to the disk_ioctl functio. */ + + + +/*---------------------------------------------------------------------------/ +/ System Configurations +/----------------------------------------------------------------------------*/ + +#define _WORD_ACCESS 0 /* 0 or 1 */ +/* Set 0 first and it is always compatible with all platforms. The _WORD_ACCESS +/ option defines which access method is used to the word data on the FAT volume. +/ +/ 0: Byte-by-byte access. +/ 1: Word access. Do not choose this unless following condition is met. +/ +/ When the byte order on the memory is big-endian or address miss-aligned word +/ access results incorrect behavior, the _WORD_ACCESS must be set to 0. +/ If it is not the case, the value can also be set to 1 to improve the +/ performance and code size. +*/ + + +/* A header file that defines sync object types on the O/S, such as +/ windows.h, ucos_ii.h and semphr.h, must be included prior to ff.h. */ + +#define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */ +#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */ +#define _SYNC_t HANDLE /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */ + +/* The _FS_REENTRANT option switches the reentrancy (thread safe) of the FatFs module. +/ +/ 0: Disable reentrancy. _SYNC_t and _FS_TIMEOUT have no effect. +/ 1: Enable reentrancy. Also user provided synchronization handlers, +/ ff_req_grant, ff_rel_grant, ff_del_syncobj and ff_cre_syncobj +/ function must be added to the project. */ + + +#define _FS_SHARE 0 /* 0:Disable or >=1:Enable */ +/* To enable file shareing feature, set _FS_SHARE to 1 or greater. The value + defines how many files can be opened simultaneously. */ + + +#endif /* _FFCONFIG */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FatFileSystem/integer.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,37 @@ +/*-------------------------------------------*/ +/* Integer type definitions for FatFs module */ +/*-------------------------------------------*/ + +#ifndef _INTEGER +#define _INTEGER + +#ifdef _WIN32 /* FatFs development platform */ + +#include <windows.h> +#include <tchar.h> + +#else /* Embedded platform */ + +/* These types must be 16-bit, 32-bit or larger integer */ +typedef int INT; +typedef unsigned int UINT; + +/* These types must be 8-bit integer */ +typedef char CHAR; +typedef unsigned char UCHAR; +typedef unsigned char BYTE; + +/* These types must be 16-bit integer */ +typedef short SHORT; +typedef unsigned short USHORT; +typedef unsigned short WORD; +typedef unsigned short WCHAR; + +/* These types must be 32-bit integer */ +typedef long LONG; +typedef unsigned long ULONG; +typedef unsigned long DWORD; + +#endif + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FatFileSystem/option/ccsbcs.c Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,540 @@ +/*------------------------------------------------------------------------*/ +/* Unicode - Local code bidirectional converter (C)ChaN, 2009 */ +/* (SBCS code pages) */ +/*------------------------------------------------------------------------*/ +/* 437 U.S. (OEM) +/ 720 Arabic (OEM) +/ 1256 Arabic (Windows) +/ 737 Greek (OEM) +/ 1253 Greek (Windows) +/ 1250 Central Europe (Windows) +/ 775 Baltic (OEM) +/ 1257 Baltic (Windows) +/ 850 Multilingual Latin 1 (OEM) +/ 852 Latin 2 (OEM) +/ 1252 Latin 1 (Windows) +/ 855 Cyrillic (OEM) +/ 1251 Cyrillic (Windows) +/ 866 Russian (OEM) +/ 857 Turkish (OEM) +/ 1254 Turkish (Windows) +/ 858 Multilingual Latin 1 + Euro (OEM) +/ 862 Hebrew (OEM) +/ 1255 Hebrew (Windows) +/ 874 Thai (OEM, Windows) +/ 1258 Vietnam (OEM, Windows) +*/ + +#include "../ff.h" + + +#if _CODE_PAGE == 437 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP437(0x80-0xFF) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, + 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, + 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, + 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, + 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, + 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, + 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 720 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP720(0x80-0xFF) to Unicode conversion table */ + 0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7, + 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, + 0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627, + 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, + 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, + 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x00B5, 0x0642, + 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A, + 0x2261, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0xO650, 0x2248, + 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 737 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP737(0x80-0xFF) to Unicode conversion table */ + 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, + 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, + 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, + 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, + 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, + 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, + 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03C9, 0x03AC, 0x03AD, 0x03AE, 0x03CA, 0x03AF, 0x03CC, 0x03CD, + 0x03CB, 0x03CE, 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E, + 0x038F, 0x00B1, 0x2265, 0x2264, 0x03AA, 0x03AB, 0x00F7, 0x2248, + 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 775 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP775(0x80-0xFF) to Unicode conversion table */ + 0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107, + 0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A, + 0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4, + 0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6, + 0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0104, 0x010C, 0x0118, + 0x0116, 0x2563, 0x2551, 0x2557, 0x255D, 0x012E, 0x0160, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0172, 0x016A, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x017D, + 0x0105, 0x010D, 0x0119, 0x0117, 0x012F, 0x0161, 0x0173, 0x016B, + 0x017E, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x00D3, 0x00DF, 0x014C, 0x0143, 0x00F5, 0x00D5, 0x00B5, 0x0144, + 0x0136, 0x0137, 0x013B, 0x013C, 0x0146, 0x0112, 0x0145, 0x2019, + 0x00AD, 0x00B1, 0x201C, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x201E, + 0x00B0, 0x2219, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 850 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP850(0x80-0xFF) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, + 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, + 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, + 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, + 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE, + 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, + 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, + 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4, + 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, + 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 852 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP852(0x80-0xFF) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, + 0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106, + 0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, + 0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E, + 0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x011A, + 0x015E, 0x2563, 0x2551, 0x2557, 0x255D, 0x017B, 0x017C, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0102, 0x0103, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x0111, 0x0110, 0x010E, 0x00CB, 0x010F, 0x0147, 0x00CD, 0x00CE, + 0x011B, 0x2518, 0x250C, 0x2588, 0x2584, 0x0162, 0x016E, 0x2580, + 0x00D3, 0x00DF, 0x00D4, 0x0143, 0x0144, 0x0148, 0x0160, 0x0161, + 0x0154, 0x00DA, 0x0155, 0x0170, 0x00FD, 0x00DD, 0x0163, 0x00B4, + 0x00AD, 0x02DD, 0x02DB, 0x02C7, 0x02D8, 0x00A7, 0x00F7, 0x00B8, + 0x00B0, 0x00A8, 0x02D9, 0x0171, 0x0158, 0x0159, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 855 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP855(0x80-0xFF) to Unicode conversion table */ + 0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, + 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408, + 0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, + 0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A, + 0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414, + 0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0445, 0x0425, 0x0438, + 0x0418, 0x2563, 0x2551, 0x2557, 0x255D, 0x0439, 0x0419, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x043A, 0x041A, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x043B, 0x041B, 0x043C, 0x041C, 0x043D, 0x041D, 0x043E, 0x041E, + 0x043F, 0x2518, 0x250C, 0x2588, 0x2584, 0x041F, 0x044F, 0x2580, + 0x042F, 0x0440, 0x0420, 0x0441, 0x0421, 0x0442, 0x0422, 0x0443, + 0x0423, 0x0436, 0x0416, 0x0432, 0x0412, 0x044C, 0x042C, 0x2116, + 0x00AD, 0x044B, 0x042B, 0x0437, 0x0417, 0x0448, 0x0428, 0x044D, + 0x042D, 0x0449, 0x0429, 0x0447, 0x0427, 0x00A7, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 857 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP857(0x80-0xFF) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, + 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, + 0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F, + 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, + 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x00BA, 0x00AA, 0x00CA, 0x00CB, 0x00C8, 0x0000, 0x00CD, 0x00CE, + 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, + 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x0000, + 0x00D7, 0x00DA, 0x00DB, 0x00D9, 0x00EC, 0x00FF, 0x00AF, 0x00B4, + 0x00AD, 0x00B1, 0x0000, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, + 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 858 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP858(0x80-0xFF) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, + 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, + 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, + 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, + 0x00A9, 0x2563, 0x2551, 0x2557, 0x2550, 0x00A2, 0x00A5, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x20AC, 0x00CD, 0x00CE, + 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00C6, 0x00CC, 0x2580, + 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, + 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4, + 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, + 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 862 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP862(0x80-0xFF) to Unicode conversion table */ + 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, + 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, + 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, + 0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, + 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, + 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, + 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, + 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 866 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP866(0x80-0xFF) to Unicode conversion table */ + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, + 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, + 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, + 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, + 0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E, + 0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 874 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP874(0x80-0xFF) to Unicode conversion table */ + 0x20AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x2026, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, + 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, + 0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17, + 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F, + 0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27, + 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F, + 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, + 0x0E38, 0x0E39, 0x0E3A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0E3F, + 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47, + 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F, + 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, + 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0x0000, 0x0000, 0x0000, 0x0000 +}; + +#elif _CODE_PAGE == 1250 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP1250(0x80-0xFF) to Unicode conversion table */ + 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, + 0x0000, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x0000, 0x2122, 0x0161, 0x203A, 0x015B, 0x0165, 0x017E, 0x017A, + 0x00A0, 0x02C7, 0x02D8, 0x0141, 0x00A4, 0x0104, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x015E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x017B, + 0x00B0, 0x00B1, 0x02DB, 0x0142, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x0105, 0x015F, 0x00BB, 0x013D, 0x02DD, 0x013E, 0x017C, + 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, + 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, + 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, + 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, + 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, + 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F, + 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, + 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9 +}; + +#elif _CODE_PAGE == 1251 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP1251(0x80-0xFF) to Unicode conversion table */ + 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021, + 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F, + 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x0000, 0x2111, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F, + 0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7, + 0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407, + 0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7, + 0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457, + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, + 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, + 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F +}; + +#elif _CODE_PAGE == 1252 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP1252(0x80-0xFF) to Unicode conversion table */ + 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017D, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x017E, 0x0178, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF +}; + +#elif _CODE_PAGE == 1253 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP1253(0x80-0xFF) to Unicode conversion table */ + 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x0000, 0x2030, 0x0000, 0x2039, 0x000C, 0x0000, 0x0000, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00A0, 0x0385, 0x0386, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x0000, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x2015, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x00B5, 0x00B6, 0x00B7, + 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F, + 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, + 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, + 0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, + 0x03A8, 0x03A9, 0x03AA, 0x03AD, 0x03AC, 0x03AD, 0x03AE, 0x03AF, + 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, + 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, + 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, + 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000 +}; + +#elif _CODE_PAGE == 1254 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP1254(0x80-0xFF) to Unicode conversion table */ + 0x20AC, 0x0000, 0x210A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00BD, 0x00DC, 0x0130, 0x015E, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF +}; + +#elif _CODE_PAGE == 1255 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP1255(0x80-0xFF) to Unicode conversion table */ + 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7, + 0x05B8, 0x05B9, 0x0000, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF, + 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05F0, 0x05F1, 0x05F2, 0x05F3, + 0x05F4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, + 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, + 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, + 0x05E8, 0x05E9, 0x05EA, 0x0000, 0x0000, 0x200E, 0x200F, 0x0000 +}; + +#elif _CODE_PAGE == 1256 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP1256(0x80-0xFF) to Unicode conversion table */ + 0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688, + 0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x06A9, 0x2122, 0x0691, 0x203A, 0x0153, 0x200C, 0x200D, 0x06BA, + 0x00A0, 0x060C, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x06BE, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x061B, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x061F, + 0x06C1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, + 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, + 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00D7, + 0x0637, 0x0638, 0x0639, 0x063A, 0x0640, 0x0640, 0x0642, 0x0643, + 0x00E0, 0x0644, 0x00E2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0649, 0x064A, 0x00EE, 0x00EF, + 0x064B, 0x064C, 0x064D, 0x064E, 0x00F4, 0x064F, 0x0650, 0x00F7, + 0x0651, 0x00F9, 0x0652, 0x00FB, 0x00FC, 0x200E, 0x200F, 0x06D2 +} + +#elif _CODE_PAGE == 1257 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP1257(0x80-0xFF) to Unicode conversion table */ + 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, + 0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x00A8, 0x02C7, 0x00B8, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x00AF, 0x02DB, 0x0000, + 0x00A0, 0x0000, 0x00A2, 0x00A3, 0x00A4, 0x0000, 0x00A6, 0x00A7, + 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6, + 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112, + 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B, + 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7, + 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF, + 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113, + 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C, + 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7, + 0x0173, 0x014E, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x02D9 +}; + +#elif _CODE_PAGE == 1258 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP1258(0x80-0xFF) to Unicode conversion table */ + 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0000, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0000, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x0300, 0x00CD, 0x00CE, 0x00CF, + 0x0110, 0x00D1, 0x0309, 0x00D3, 0x00D4, 0x01A0, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x01AF, 0x0303, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0301, 0x00ED, 0x00EE, 0x00EF, + 0x0111, 0x00F1, 0x0323, 0x00F3, 0x00F4, 0x01A1, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x01B0, 0x20AB, 0x00FF +}; + +#endif + + +#if !_TBLDEF || !_USE_LFN +#error This file is not needed in current configuration. Remove from the project. +#endif + + +WCHAR ff_convert ( /* Converted character, Returns zero on error */ + WCHAR src, /* Character code to be converted */ + UINT dir /* 0: Unicode to OEMCP, 1: OEMCP to Unicode */ +) +{ + WCHAR c; + + + if (src < 0x80) { /* ASCII */ + c = src; + + } else { + if (dir) { /* OEMCP to Unicode */ + c = (src >= 0x100) ? 0 : Tbl[src - 0x80]; + + } else { /* Unicode to OEMCP */ + for (c = 0; c < 0x80; c++) { + if (src == Tbl[c]) break; + } + c = (c + 0x80) & 0xFF; + } + } + + return c; +} + + +WCHAR ff_wtoupper ( /* Upper converted character */ + WCHAR chr /* Input character */ +) +{ + static const WCHAR tbl_lower[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xA1, 0x00A2, 0x00A3, 0x00A5, 0x00AC, 0x00AF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0x0FF, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x10D, 0x10F, 0x111, 0x113, 0x115, 0x117, 0x119, 0x11B, 0x11D, 0x11F, 0x121, 0x123, 0x125, 0x127, 0x129, 0x12B, 0x12D, 0x12F, 0x131, 0x133, 0x135, 0x137, 0x13A, 0x13C, 0x13E, 0x140, 0x142, 0x144, 0x146, 0x148, 0x14B, 0x14D, 0x14F, 0x151, 0x153, 0x155, 0x157, 0x159, 0x15B, 0x15D, 0x15F, 0x161, 0x163, 0x165, 0x167, 0x169, 0x16B, 0x16D, 0x16F, 0x171, 0x173, 0x175, 0x177, 0x17A, 0x17C, 0x17E, 0x192, 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6, 0x3B7, 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC, 0x3BD, 0x3BE, 0x3BF, 0x3C0, 0x3C1, 0x3C3, 0x3C4, 0x3C5, 0x3C6, 0x3C7, 0x3C8, 0x3C9, 0x3CA, 0x430, 0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F, 0x440, 0x441, 0x442, 0x443, 0x444, 0x445, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x451, 0x452, 0x453, 0x454, 0x455, 0x456, 0x457, 0x458, 0x459, 0x45A, 0x45B, 0x45C, 0x45E, 0x45F, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0 }; + static const WCHAR tbl_upper[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x21, 0xFFE0, 0xFFE1, 0xFFE5, 0xFFE2, 0xFFE3, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0x178, 0x100, 0x102, 0x104, 0x106, 0x108, 0x10A, 0x10C, 0x10E, 0x110, 0x112, 0x114, 0x116, 0x118, 0x11A, 0x11C, 0x11E, 0x120, 0x122, 0x124, 0x126, 0x128, 0x12A, 0x12C, 0x12E, 0x130, 0x132, 0x134, 0x136, 0x139, 0x13B, 0x13D, 0x13F, 0x141, 0x143, 0x145, 0x147, 0x14A, 0x14C, 0x14E, 0x150, 0x152, 0x154, 0x156, 0x158, 0x15A, 0x15C, 0x15E, 0x160, 0x162, 0x164, 0x166, 0x168, 0x16A, 0x16C, 0x16E, 0x170, 0x172, 0x174, 0x176, 0x179, 0x17B, 0x17D, 0x191, 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F, 0x3A0, 0x3A1, 0x3A3, 0x3A4, 0x3A5, 0x3A6, 0x3A7, 0x3A8, 0x3A9, 0x3AA, 0x410, 0x411, 0x412, 0x413, 0x414, 0x415, 0x416, 0x417, 0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E, 0x41F, 0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427, 0x428, 0x429, 0x42A, 0x42B, 0x42C, 0x42D, 0x42E, 0x42F, 0x401, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, 0x408, 0x409, 0x40A, 0x40B, 0x40C, 0x40E, 0x40F, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A, 0 }; + int i; + + + for (i = 0; tbl_lower[i] && chr != tbl_lower[i]; i++) ; + + return tbl_lower[i] ? tbl_upper[i] : chr; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FechaHora.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,174 @@ +#include "FechaHora.h" + +void FechaHora::update(){ + time(&rawtime); + timeinfo = localtime(&rawtime); +} + +void FechaHora::updateRawTime(){ // Actualiza el número de segundos desde el 1 de enero de 1970 + rawtime = mktime(timeinfo); + set_time(rawtime); +} + +// Funciones que devuelven la fecha y hora como enteros +int FechaHora::getNsecond(){ + return timeinfo->tm_sec; +} + +int FechaHora::getNminute(){ + return timeinfo->tm_min; +} + +int FechaHora::getNhour(){ + return timeinfo->tm_hour; +} + +int FechaHora::getNday(){ + return timeinfo->tm_mday; +} + +int FechaHora::getNmonth(){ + return timeinfo->tm_mon + 1; +} + +int FechaHora::getNyear(){ // años desde 1900 + return timeinfo->tm_year; +} + +// Funciones que configuran la fecha y hora +void FechaHora::setNsecond(int n){ + timeinfo->tm_sec = n; +} + +void FechaHora::setNminute(int n){ + timeinfo->tm_min = n; +} + +void FechaHora::setNhour(int n){ + timeinfo->tm_hour = n; +} + +void FechaHora::setNday(int n){ + timeinfo->tm_mday = n; +} + +void FechaHora::setNmonth(int n){ + timeinfo->tm_mon = (n - 1); +} + +void FechaHora::setNyear(int n){ // años desde 1900 + timeinfo->tm_year = n; +} + +char *FechaHora::getFechaHora(){ + char aux[5]; + memset(fechaHoraFormat,'\0',strlen(fechaHoraFormat)); + + getDay(aux); + strncpy(fechaHoraFormat, aux, 2); + + strcat(fechaHoraFormat, "-"); + + getMonth(aux); + strncat(fechaHoraFormat, aux, 2); + + strcat(fechaHoraFormat, "-"); + + getYear(aux); + strncat(fechaHoraFormat, aux, 4); + + strcat(fechaHoraFormat, " "); + + getHour(aux); + strncat(fechaHoraFormat, aux, 2); + + strcat(fechaHoraFormat, ";"); + + getMinute(aux); + strncat(fechaHoraFormat, aux, 2); + + strcat(fechaHoraFormat, ";"); + + getSecond(aux); + strncat(fechaHoraFormat, aux, 2); + + return fechaHoraFormat; +} + +char *FechaHora::getFecha(){ + char aux[5]; + memset(fechaHoraFormat,'\0',strlen(fechaHoraFormat)); + + getDay(aux); + strncpy(fechaHoraFormat, aux, 2); + + strcat(fechaHoraFormat, "-"); + + getMonth(aux); + strncat(fechaHoraFormat, aux, 2); + + strcat(fechaHoraFormat, "-"); + + getYear(aux); + strncat(fechaHoraFormat, aux, 4); + + return fechaHoraFormat; +} + +char *FechaHora::getHora(){ + char aux[5]; + memset(fechaHoraFormat,'\0',strlen(fechaHoraFormat)); + + getHour(aux); + strncpy(fechaHoraFormat, aux, 2); + + strcat(fechaHoraFormat, ";"); + + getMinute(aux); + strncat(fechaHoraFormat, aux, 2); + + strcat(fechaHoraFormat, ";"); + + getSecond(aux); + strncat(fechaHoraFormat, aux, 2); + + return fechaHoraFormat; +} + + +// Funciones que devuelven la hora +void FechaHora::getSecond(char buff[]){ + intTo2char(timeinfo->tm_sec, buff); +} +void FechaHora::getMinute(char buff[]){ + intTo2char(timeinfo->tm_min, buff); +} +void FechaHora::getHour(char buff[]){ + intTo2char(timeinfo->tm_hour, buff); +} + +// Funciones que devuelven la fecha +void FechaHora::getDay(char buff[]){ + intTo2char(timeinfo->tm_mday, buff); +} +void FechaHora::getMonth(char buff[]){ + intTo2char(timeinfo->tm_mon+1, buff); +} +void FechaHora::getYear(char buff[]){ + int year = 1900 + timeinfo->tm_year; + intTo4char(year, buff); +} + +// La siguiente función devuelve los dos caracteres correspondientes a las dos cifras de un número entre 0 y 99 pasado como argumento (sin signo) +void FechaHora::intTo2char(int value, char buff[]){ + buff[0] = value/10 + '0'; // Decenas + buff[1] = value - ((int)(value/10))*10 + '0'; // unidades +} + +// La siguiente función devuelve los dos caracteres correspondientes a las dos cifras de un número entre 0 y 99 pasado como argumento (sin signo) +void FechaHora::intTo4char(int value, char buff[]){ + buff[0] = value/1000 + '0'; // Millares + buff[1] = ((int)(value - ((int)(value/1000))*1000))/100 + '0'; // Centenas + buff[2] = (value - (buff[0] - '0')*1000 - (buff[1] - '0')*100)/10 + '0'; + buff[3] = (value - (buff[0] - '0')*1000 - (buff[1] - '0')*100 - (buff[2] - '0')*10) + '0'; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FechaHora.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,69 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#ifndef FECHAHORA_H +#define FECHAHORA_H + +#include "mbed.h" +#include <time.h> +#include <string.h> + +// Clase que controla la fecha y la hora del dispositivo +class FechaHora{ + public: + + // LLamar esta función para antes de llamar las funciones que devuelven la fecha y hora para actualizarlas internamente + void update(); + + void updateRawTime(); // Actualiza el número de segundos desde el 1 de enero de 1970 + + //Esta función devuelve la fecha y la hora con le siguiente formato: XX-XX-XX XX;XX;XX + char *getFechaHora(); + + // Estas dos funciones devuelven la fecha o la hora individualmente + char *getFecha(); + char *getHora(); + + // Funciones que devuelven la hora como caracteres + void getSecond(char buff[]); + void getMinute(char buff[]); + void getHour(char buff[]); + + // Funciones que devuelven la fecha como caracteres + void getDay(char buff[]); + void getMonth(char buff[]); + void getYear(char buff[]); + + // Funciones que devuelven la fecha y hora como enteros + int getNsecond(); + int getNminute(); + int getNhour(); + + int getNday(); + int getNmonth(); + int getNyear(); // años desde 1900 + + // Funciones que configuran la fecha y hora + void setNsecond(int n); + void setNminute(int n); + void setNhour(int n); + + void setNday(int n); + void setNmonth(int n); + void setNyear(int n); // años desde 1900 + + private: + char fechaHoraFormat[32]; + time_t rawtime; + struct tm * timeinfo; + + // La siguiente función devuelve los dos caracteres correspondientes a las dos cifras de un número entre 0 y 99 pasado como argumento (sin signo) + void intTo2char(int value, char buff[]); + + // La siguiente función devuelve los cuatro caracteres correspondientes a las dos cifras de un número entre 0 y 9999 pasado como argumento (sin signo) + void intTo4char(int value, char buff[]); + +}; + + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FileManager/Configuracion.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,111 @@ +#include "Configuracion.h" + +extern ScreenManager SC; +extern SelecManager SM; + +Configuracion::Configuracion(){ + // Se lee el archivo de configuración, en caso de no existir se crea + FILE* file; + if((file = fopen("/local/Config.vme","r")) == NULL){ + setDefaults(); + createFile(); + }else{ // El archivo ya existe + getParam(file, "adquisitionvelocity", velocidadAdquisicion); + getParam(file, "languaje", idioma); + getParam(file, "selectiontype", formaSeleccion); + } + // Se cierra el fichero + if(file != NULL){ + fclose(file); + } +} + +void Configuracion::restoreSettings(){ + setDefaults(); + createFile(); +} + +void Configuracion::setDefaults(){ + strcpy(velocidadAdquisicion, "1000"); + strcpy(idioma, "spanish"); + strcpy(formaSeleccion, "shading"); + + // Además del fichero de configuración se cambia la configuración actual de la interfaz + char aux[16]; + // Se selecciona el idioma + getIdioma(aux); + if(strcmp(aux, "spanish") == 0){ + SC.selectGroup(0); + }else if(strcmp(aux, "english") == 0){ + SC.selectGroup(1); + } + // Se selecciona el modo de selección + getFormaSeleccion(aux); + if(strcmp(aux, "shading") == 0){ + SM.setInverterSelection(); + }else if(strcmp(aux, "framing") == 0){ + SM.setRectSelection(); + } +} + +// Esta función busca el valor del parámetro nameParam y lo guarda en buf +// Para ello se recorrera cada una de las lineas del archivo de configuración hasta encontrarlo y leer su valor +// Recordar: El archivo de configuración tiene le siguiente formato +// nombreParámetro valorParámetro +void Configuracion::getParam(FILE* file, char nameParam[], char buf[]){ + // se calcula la longitud del nombre del parámetro + int lenParam = strlen(nameParam); + char aux[NCARACTERESLECTURA]; + bool encontrado = false; + while(!encontrado && (!feof(file))){ // Solo se para de leer si se ha llegado al fin de fichero o se ha encontrado el valor del parámetro + // Se lee una linea + fgets(aux, NCARACTERESLECTURA, file); + if(strncmp(nameParam, aux, lenParam)== 0){ + // Se ha encontrado la línea del parámetro que está guardada en aux + // se guarda el valor del parámetro (que empieza después de un espacio desde el nombre del parámetro y acaba antes del salto de línea) + // Antes se calcula cuantos caracteres tiene el valor del parámetro + // que será la longitud de la línea menos a longitud del nombre del parámetro - 2 (un caracter que es el espacio y el caracter final \n que tampoco debe copiarse + for(int i = 0; i < strlen(aux) - lenParam - 2; i++){ + buf[i] = aux[i + lenParam + 1]; // +1 porque se empieza a guardar a partir del espacio entre el nombre y el valor + } + encontrado = true; + } + } +} + +void Configuracion::createFile(){ + FILE* file = fopen("/local/Config.vme","w"); + fprintf(file, "adquisitionvelocity %s\n", velocidadAdquisicion); + fprintf(file, "languaje %s\n", idioma); + fprintf(file, "selectiontype %s\n", formaSeleccion); + fclose(file); +} + +void Configuracion::setVelocidadAdquision(int nuevaVelocidadAdqusicion){ + sprintf(velocidadAdquisicion,"%d",nuevaVelocidadAdqusicion); + createFile(); +} +void Configuracion::setIdioma(char nuevoIdioma[]){ + strcpy(idioma, nuevoIdioma); + createFile(); +} +void Configuracion::setFormaSeleccion(char nuevaFormaSeleccion[]){ + strcpy(formaSeleccion, nuevaFormaSeleccion); + createFile(); +} + +int Configuracion::getVelocidadAdquisicion(){ + return atoi(velocidadAdquisicion); +} + +void Configuracion::getVelocidadAdquisicionString(char buff[]){ + strcpy(buff, velocidadAdquisicion); +} + +void Configuracion::getIdioma(char buf[]){ + strcpy(buf, idioma); +} + +void Configuracion::getFormaSeleccion(char buf[]){ + strcpy(buf, formaSeleccion); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FileManager/Configuracion.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,48 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#ifndef CONFIGURACION_H +#define CONFIGURACION_H + +#define NCARACTERES 16 +#define NCARACTERESLECTURA 64 + +#include "mbed.h" +#include "ScreenManager.h" +#include "SelecManager.h" +#include <string.h> +#include <stdlib.h> + +// CLase encargada de guardar y cargar la configuración +class Configuracion{ + public: + Configuracion(); // EL construtor carga los valores de configuracion o crea una configuracion inicial en caso de no existir + + void getVelocidadAdquisicionString(char buff[]); + int getVelocidadAdquisicion(); + void getIdioma(char buf[]); + void getFormaSeleccion(char buf[]); + + void setVelocidadAdquision(int nuevaVelocidadAdqusicion); + void setIdioma(char nuevoIdioma[]); + void setFormaSeleccion(char nuevaFormaSeleccion[]); + + + void restoreSettings(); // Vuelve a los valóres de fábrica + + private: + // Parámetros + char velocidadAdquisicion[NCARACTERES]; + char idioma[NCARACTERES]; + char formaSeleccion[NCARACTERES]; + + void getParam(FILE* file, char nameParam[], char buf[]); + void createFile(); // Crea o sobreescribe un archivo con los parámetros de configuración + + void setDefaults(); // Carga los valores predeterminados + + +}; + + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FileManager/ParametrosCalibracion.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,56 @@ +#include "ParametrosCalibracion.h" + +extern ScreenManager SC; +extern SelecManager SM; + + +void ParametrosCalibracion::leerValores(float* valores){ // Esta función guarda en un array de 6 float los valores de calibración + // Se lee el archivo de valores de calibracion + FILE* file; + if((file = fopen("/local/Calibrat.vme","rb")) == NULL){ // Si no existe + // Se crea un fichero con valores por defecto + createDefaults(); + // Se devuelven los valores por defecto + valores[0] = AX; + valores[1] = AY; + valores[2] = AZ; + valores[3] = KX; + valores[4] = KY; + valores[5] = KZ; + }else{ // El archivo ya existe + // Se leen los 6 valores y se guardan en la dirección pasada como argumento + fread(valores, 4, 6, file); + } + // Se cierra el fichero + if(file != NULL){ + fclose(file); + } +} + +void ParametrosCalibracion::createDefaults(){ // Esta función guarda en un array de 6 float los valores de calibración + // Se cre un archivo con los valores por defecto de calibración + FILE* file; + file = fopen("/local/Calibrat.vme","wb"); + + // datos a aguradar en el fichero + float datos[] = {AX, AY, AZ, KX, KY, KZ}; + + // Tamaño de los datos: 32 bits (4 bytes), número de datos : 6 + fwrite(datos, 4, 6, file); + + // Se cierra el fichero + fclose(file); +} + +// Guarda 6 nuevos valores de calibración +void ParametrosCalibracion::saveValores(float valores[]){ // Esta función guarda en un array de 6 float los valores de calibración + // Se cre un archivo con los valores por defecto de calibración + FILE* file; + file = fopen("/local/Calibrat.vme","wb"); + + // Tamaño de los datos: 32 bits (4 bytes), número de datos: 6 + fwrite(valores, 4, 6, file); + + // Se cierra el fichero + fclose(file); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FileManager/ParametrosCalibracion.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,37 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#ifndef PARAMETROSCALIBRACION_H +#define PARAMETROSCALIBRACION_H + +#define NCARACTERES 16 +#define NCARACTERESLECTURA 64 + +#include "mbed.h" +#include "ScreenManager.h" +#include "SelecManager.h" +#include <string.h> +#include <stdlib.h> + +// Valores de calibración por defecto +// OFFSET +#define AX 2086.500488 +#define AY 2070.410645 +#define AZ 2057.436523 +// Sensibilidad +#define KX 0.011837 +#define KY 0.011808 +#define KZ 0.011850 + +// Clase encargada de guardar y cargar los parámetros de calibración del sensor +// En total son 6 parámetros: +// 3 de offset y 3 de conversión a unidades física +class ParametrosCalibracion{ + public: + static void leerValores(float* valores); // Esta función guarda en un array de 6 float los valores de calibración + static void createDefaults(); // Crea un fichero de valores de calibración. Dichos valores serán los valores por defecto + static void saveValores(float valores[]); // Guarda 6 nuevos valores de calibración +}; + + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FileManager/SistemaArchivos.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,186 @@ +#include "SistemaArchivos.h" + +extern ScreenManager SC; +extern MSCFileSystem msc; + +extern DigitalOut myled; + +SistemaArchivos::SistemaArchivos(){ + nViajes = 0; +} + +void SistemaArchivos::addElement(char newElement[]){ + FILE* file = fopen("/local/RideList.vme","a"); + fprintf(file, "%s\n", newElement); + fclose(file); +} + +int SistemaArchivos::reloadRideNames(){ + // Se reinicia el número de viajes + nViajes = 0; + // Se abre el archivo de nombres de viajes + FILE* file = fopen("/local/RideList.vme","r"); + if(file == NULL){ + return 1; + }else{ + while(!feof(file)){ // Mientras no se haya llegado al fin de fichero + //strcpy(names[nViajes], readTextLine(file)); + fgets(names[nViajes], NCARACTERES, file); + // Se borra el último caracter de la cadena, el caracter '\n' + deleteLastChar(names[nViajes]); + //fscanf(file, "%s", names[nViajes]); + nViajes++; + } + // La última cadena es '\n', esta no se contara como cadena + nViajes--; + fclose(file); + return 0; + } +} + +int SistemaArchivos::deleteRide(char *fileName){ // Borra los archivos asociados a un viaje, y lo borra de la lista de viajes + char file[64]; + + // Primero se intenta borrar el archivo de la memoria flash + strcpy(file, "/usb/"); + strcat(file, fileName); + strcat(file, ".txt"); + + if(remove(file) != 0){ // Si no se pudo borrar se devuelve un 1 + return 1; + }else{ // Si se borró el archivo se borra también de la lista de viajes + // Para ello primero se borra el viaje del array "names" + // Procedimiento: + // - Se busca el nombre en la lista + // - Una vez encontrada su posición todos los elementos por debajo de este se suben una posición + int pos = 0; + + // - Se busca el nombre en la lista + while(strcmp(names[pos], fileName)){ + pos++; + } + + // En este momento la variable "pos" guarda la posición de memoria de el elemento a borrar + // Se aumenta en uno este índice para subir de posición los elementos por debajo de este + pos++; + + // - Una vez encontrada su posición todos los elementos por debajo de este se suben una posición + for (int i = pos; i < nViajes; i++){ + strcpy(names[i-1], names[i]); + } + + // El número de viajes es una unidad menor + nViajes--; + + // Se guarda la nueva lista de viajes + saveRideList(); + + return 0; + } +} + +int SistemaArchivos::renameRide(char *fileName, char *newName){ // Cambia el nombre de los archivos asociados a un viaje, y de la lista de viajes + char oldFile[64]; + char newFile[64]; + + // Primero se intenta cambiar el nombre del archivo de la memoria flash + strcpy(oldFile, "/usb/"); + strcat(oldFile, fileName); + strcat(oldFile, ".txt"); + + strcpy(newFile, "/usb/"); + strcat(newFile, newName); + strcat(newFile, ".txt"); + + if(file_rename(oldFile, newFile) != 0){ // Si no se pudo borrar se devuelve un 1 + return 1; + }else{ // Si se cambió el nombre del archivo también se cambia el nombre en la lista de viajes + // Procedimiento: + // - Se busca el nombre antiguo en la lista + // - Una vez encontrada su posición se cambia su nombre + int pos = 0; + + // - Se busca el nombre antiguo en la lista + while(strcmp(names[pos], fileName)){ + pos++; + } + + // - Una vez encontrada su posición se cambia su nombre + strcpy(names[pos], newName); + + // Se guarda la nueva lista de viajes + saveRideList(); + + return 0; + } +} + +bool SistemaArchivos::alredyExist(char *name){ + bool value = false; + for(int i = 0; i < nViajes; i++){ + if(!strcmp(names[i], name)){ + value = true; + } + } + return value; +} + +void SistemaArchivos::saveRideList(){ + // Se sobreescribe el archivo "RideList.vme" con la lista de el array nombres + FILE* file = fopen("/local/RideList.vme","w"); + for(int i = 0; i < nViajes; i++){ + fprintf(file, "%s\n", names[i]); + } + fclose(file); +} + +char* SistemaArchivos::getNameRide(int nameNumber){ + return names[nameNumber]; +} + +int SistemaArchivos::getNrides(){ + return nViajes; +} + +//*********************************************************** +// file_rename: renames a file. +// Kind of hoakey as it moves data instead of adjusting +// the file name in the directory. +// Checks to insure the file was renamed. +// Returns -1 = error; 0 = success +//*********************************************************** +int SistemaArchivos::file_rename(const char *oldfile, const char *newfile) { + int retval = 0; + int ch; + + FILE *fpold = fopen(oldfile, "r"); + if(fpold == NULL) { + retval = (-1); + }else{ + FILE *fpnew = fopen(newfile, "w"); + + while (1) { + ch = fgetc(fpold); + if (ch == EOF) break; + fputc(ch, fpnew); + } + + fclose(fpnew); + fclose(fpold); + + fpnew = fopen(newfile, "r"); + if(fpnew == NULL) { + retval = (-1); + } + else { + remove(oldfile); + } + fclose(fpnew); + } + return (retval); +} + +void SistemaArchivos::deleteLastChar(char *str){ // Borra el último caracter de una cadena + str[strlen(str)-1] = '\0'; +} + \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FileManager/SistemaArchivos.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,60 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#ifndef SISTEMAARCHIVOS_H +#define SISTEMAARCHIVOS_H + +#define NMAXVIAJES 100 +#define NCARACTERES 28 +#define NCARACTERESLECTURA 64 + +#include "mbed.h" +#include "ScreenManager.h" +#include "MSCFileSystem.h" +#include "SelecManager.h" +#include <string.h> +#include <stdlib.h> + +// Esta clase va a gestionar los archivos que guardan los datos recogidos del acelerómetro +// La filosofía de funcionamiento es la siguiente: +// En la memoria flash externa se guardarán los archivos con los datos +// Como se va a necesitar cargar estos archivos en otro momento o incluso cambiarles el nombre, se guardará en la memoria flash de la mbed una lista con los nombres de los archivosde datos y así independientemente de su nombre +// puedan encontrarse y cargarse. +// En definitiva esta clase controlará esta lista de nombres de archivos +class SistemaArchivos{ + public: + SistemaArchivos(); // EL construtor carga los valores de configuracion o crea una configuracion inicial en caso de no existir + + void addElement(char newElement[]); // Esta función añade un nuevo nombre de archivo a la lista + + int reloadRideNames(); // Esta función carga en memoria los nombres de los viajes guardados en el archivo RideList.txt y guarda el número de viajes + // Devuelve 0 si se recargo correctamente o 1 si no se pudo acceder al archivo de la lista de viajes. + char *getNameRide(int nameNumber); // Esta función devuelve un puntero a la lista de nombres de los viajes + int getNrides(); + + bool alredyExist(char *name); // Comprueba si nombre pasado como argumento está o no en la lista de nombres de los viajes + + int file_rename(const char *oldfile, const char *newfile); // Cambia el nombre de un archivo de la memoria flash + + // Funciones para modificar la lista de viajes: "RideList.txt", antes de usar estas funciones + // llamar a la función "reloadRideNames() para actualizar la lista de viajes en memoria + // También modifican los archivos en la memoria flash + // Estas funciones devuelven 0 en caso de haber podido ejecutarse correctamente o 1 en caso de error + int deleteRide(char *fileName); // Borra los archivos asociados a un viaje, y lo borra de la lista de viajes + int renameRide(char *fileName, char *newName); // Cambia el nombre de los archivos asociados a un viaje, y de la lista de viajes + + + private: + + char names[NMAXVIAJES][NCARACTERES]; + + void saveRideList(); // Guarda en el archivo "RideList.txt" la lista de nombres guardados en el array names sobreescribiendo los anteriores + // Devuelve 1 si no se ha podido acceder al archivo + + int nViajes; + + void deleteLastChar(char *str); // Borra el último caracter de una cadena +}; + + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/KXR94/KXR94.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,88 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ + +#include "KXR94.h" + +KXR94::KXR94(PinName mosi, PinName miso, PinName sck, PinName cs) : spi_(mosi, miso, sck), nCS_(cs) +{ + // Se configura el puerto SPI + spi_.frequency(4000000); // El máximo según el datasheet es 5MHz + spi_.format(8,0); + + // Se prepara el acelerómetro para comenzar las lecturas + AcelerometroWakeUp(); +} + +void KXR94::ReadAccels_KXR94(int* Acc) { + char x_lsb, x_msb; + char y_lsb, y_msb; + char z_lsb, z_msb; + signed short ax, ay, az; + + //------------X---------------- + nCS_ = 0; + spi_.write(CONVERTX); + wait_us(40); + x_msb = spi_.write(0x00); // Dummy byte + x_lsb = spi_.write(0x00); // Dummy byte + nCS_ = 1; + wait_us(1); + ax = (x_msb << 8) | x_lsb ; // combineer msb en lsb + ax = ax >> 4; // Get rid of four non-value bits in LSB + ax &=~0xF000; + //------------Y---------------- + nCS_ = 0; + spi_.write(CONVERTY); + wait_us(40); + y_msb = spi_.write(0x00); // Dummy byte + y_lsb = spi_.write(0x00); // Dummy byte + nCS_ = 1; + wait_us(1); + ay = (y_msb << 8) | y_lsb; // combineer msb en lsb + ay = ay >> 4; // Get rid of four non-value bits in LSB + ay &=~0xF000; + //------------Z---------------- + nCS_ = 0; + spi_.write(CONVERTZ); + wait_us(40); + z_msb = spi_.write(0x00); // Dummy byte + z_lsb = spi_.write(0x00); // Dummy byte + nCS_ = 1; + wait_us(1); + az = (z_msb << 8) | z_lsb; // combineer msb en lsb + az = az >> 4; // Get rid of four non-value bits in LSB + az &=~0xF000; + + Acc[0] = ax; + Acc[1] = ay; + Acc[2] = az; +} + +//-----------------READ OUT the X-Y-Z values--------------- +char KXR94::read_reg() { + char byte; + nCS_ = 0; + spi_.write(READREG); + byte = spi_.write(0x00); // Dummy byte + nCS_ = 1; + wait_us(1); + return byte; +} + +void KXR94::AcelerometroSleep(void) +{ + nCS_ = 0; + spi_.write(WRITEREG); + spi_.write(0x00); // Enable = 0 + nCS_ = 1; + wait_us(1); +} +void KXR94::AcelerometroWakeUp(void) +{ + nCS_ = 0; + spi_.write(WRITEREG); + spi_.write(0x04); // Enable = 1 + nCS_ = 1; + wait_us(1); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/KXR94/KXR94.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,60 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ + +#ifndef KXR94_H +#define KXR94_H + +#include "mbed.h" + +#define CONVERTX 0x00 +#define CONVERTY 0x01 +#define CONVERTZ 0x02 +#define READREG 0x03 +#define WRITEREG 0x04 +#define CONVERTAUX 0x05 + + +/*-------------Hardware connections------------- +VIO----- mbed Vout (3.3 Volt) +SDI----- mbed mosi (p5) +SDO----- mbed miso (p6) +SCK----- mbed sck (p7) +CS------ mbed (p8) // chip select +GND----- mbed GND (0 Volt) +VDO----- mbed Vout (3.3 Volt) +there are no additional external components used +//----------------------------------------------*/ + +/** + * KXR94 triple axis, digital interface, accelerometer. + */ +class KXR94 { + +public: + /** + * Constructor. + * + * @param mosi mbed pin to use for MOSI line of SPI interface. + * @param miso mbed pin to use for MISO line of SPI interface. + * @param sck mbed pin to use for SCK line of SPI interface. + * @param cs mbed pin to use for not chip select line of SPI interface. + */ + KXR94(PinName mosi, PinName miso, PinName sck, PinName cs); + + void write_reg(char data); + char read_reg(); + + void ReadAccels_KXR94(int*); + + void AcelerometroSleep(void); //Pone el acelerometro en sleep mode para no consumir energía + void AcelerometroWakeUp(void); //Pone el acelerometro preparado para medir + + private: + + SPI spi_; + DigitalOut nCS_; + +}; + +#endif /* KXR94_H */ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MSCFileSystem.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,113 @@ +/* USB Mass Storage device file system + * Copyrigh (c) 2010, Igor Skochinsky + * based on SDFileStorage + * Copyright (c) 2008-2009, sford + */ + +/* Introduction + * ------------ + * TODO: write one + * we're basically using NXP's USBHotLite sample code, just plugging in our own FAT library + */ + +#include "MSCFileSystem.h" +#include "usbhost_inc.h" + +MSCFileSystem::MSCFileSystem(const char* name) : + FATFileSystem(name) +{ +} + +void print_inquiry(USB_INT08U *inqReply) +{ + // see USB Mass Storage Class – UFI Command Specification, + // 4.2 INQUIRY Command + printf("Inquiry reply:\n"); + uint8_t tmp = inqReply[0]&0x1F; + printf("Peripheral device type: %02Xh\n", tmp); + if ( tmp == 0 ) + printf("\t- Direct access (floppy)\n"); + else if ( tmp == 0x1F ) + printf("\t- none (no FDD connected)\n"); + else + printf("\t- unknown type\n"); + tmp = inqReply[1] >> 7; + printf("Removable Media Bit: %d\n", tmp); + tmp = inqReply[2] & 3; + printf("ANSI Version: %02Xh\n", tmp); + if ( tmp != 0 ) + printf("\t- warning! must be 0\n"); + tmp = (inqReply[2]>>3) & 3; + printf("ECMA Version: %02Xh\n", tmp); + if ( tmp != 0 ) + printf("\t- warning! should be 0\n"); + tmp = inqReply[2]>>6; + printf("ISO Version: %02Xh\n", tmp); + if ( tmp != 0 ) + printf("\t- warning! should be 0\n"); + tmp = inqReply[3] & 0xF; + printf("Response Data Format: %02Xh\n", tmp); + if ( tmp != 1 ) + printf("\t- warning! should be 1\n"); + tmp = inqReply[4]; + printf("Additional length: %02Xh\n", tmp); + if ( tmp != 0x1F ) + printf("\t- warning! should be 1Fh\n"); + printf("Vendor Information: '%.8s'\n", &inqReply[8]); + printf("Product Identification: '%.16s'\n", &inqReply[16]); + printf("Product Revision: '%.4s'\n", &inqReply[32]); +} + +int MSCFileSystem::initialise_msc() +{ + USB_INT32S rc; + USB_INT08U inquiryResult[INQUIRY_LENGTH]; + + //print_clock(); + Host_Init(); /* Initialize the host controller */ + rc = Host_EnumDev(); /* Enumerate the device connected */ + if (rc != OK) + { + fprintf(stderr, "Could not enumerate device: %d\n", rc); + return rc; + } + + + /* Initialize the mass storage and scsi interfaces */ + rc = MS_Init( &_blkSize, &_numBlks, inquiryResult ); + if (rc != OK) + { + fprintf(stderr, "Could not initialize mass storage interface: %d\n", rc); + return rc; + } + printf("Successfully initialized mass storage interface; %d blocks of size %d\n", _numBlks, _blkSize); + print_inquiry(inquiryResult); + // FATFileSystem supports only 512-byte blocks + return _blkSize == 512 ? OK : 1; +} + +int MSCFileSystem::disk_initialize() +{ + if ( initialise_msc() != OK ) + return 1; + + return 0; +} + +int MSCFileSystem::disk_write(const char *buffer, int block_number) +{ + if ( OK == MS_BulkSend(block_number, 1, (USB_INT08U *)buffer) ) + return 0; + return 1; +} + +int MSCFileSystem::disk_read(char *buffer, int block_number) +{ + if ( OK == MS_BulkRecv(block_number, 1, (USB_INT08U *)buffer) ) + return 0; + return 1; +} + +int MSCFileSystem::disk_status() { return 0; } +int MSCFileSystem::disk_sync() { return 0; } +int MSCFileSystem::disk_sectors() { return _numBlks; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MSCFileSystem.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,49 @@ +/* USB Mass Storage device file system + * Copyrigh (c) 2010, Igor Skochinsky + * based on SDFileStorage + * Copyright (c) 2008-2009, sford + */ + +#ifndef MSCFILESYSTEM_H +#define MSCFILESYSTEM_H + +#include "mbed.h" +#include "FATFileSystem.h" + +/* Class: MSCFileSystem + * Access the filesystem on an attached USB mass storage device (e.g. a memory stick) + * + * Example: + * > MSCFileSystem msc("msc"); + * > + * > int main() { + * > FILE *fp = fopen("/msc/myfile.txt", "w"); + * > fprintf(fp, "Hello World!\n"); + * > fclose(fp); + * > } + */ +class MSCFileSystem : public FATFileSystem { +public: + + /* Constructor: MSCFileSystem + * Create the File System for accessing a USB mass storage device + * + * Parameters: + * name - The name used to access the filesystem + */ + MSCFileSystem(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 initialise_msc(); + uint32_t _numBlks; + uint32_t _blkSize; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pantallas/ArchivoGuardado.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,55 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#include "ArchivoGuardado.h" + +extern ScreenManager SC; +extern FechaHora FH; + +ArchivoGuardado::ArchivoGuardado(char nextScreen[], char newAdvice[], char newnameTitle[], char newdateTitle[], char newtimeTitle[]){ + strcpy(nextScreenID, nextScreen); + strcpy(advice, newAdvice); + + strcpy(nameTitle, newnameTitle); + strcpy(dateTitle, newdateTitle); + strcpy(timeTitle, newtimeTitle); +} + +void ArchivoGuardado::button5pressed(DogMLCD* lcd){ + SC.changeScreen(nextScreenID); +} + +void ArchivoGuardado::initialize(DogMLCD* lcd){ + // select font to use: + lcd->XFont = xfont_8; + + // Se escribe el nombre + lcd->XString(OFFSETXTITLES, OFFSETY, nameTitle); + + // NOTA: No se debe llamar a FHupdate() porque sino se actualizaría la hora y lo que queremos mostrar es la hora del último archivo guardado que fue la última vez que se actualizo la hora + char fileName[64]; + char auxTime[64]; + strcpy(auxTime, FH.getFechaHora()); + strcpy(fileName, "RAW"); + strcat(fileName, auxTime); + lcd->XString(OFFSETX - 2, OFFSETY + 8, fileName); // Cambiar + + // Se escribe la fecha + lcd->XString(OFFSETXTITLES, OFFSETY + 8*2, dateTitle); + lcd->XString(OFFSETX, OFFSETY + 8*3, FH.getFecha()); // Cambiar + + // Se escribe el tiempo + lcd->XString(OFFSETXTITLES, OFFSETY + 8*4, timeTitle); + + char aux[16]; + strcpy(aux, FH.getHora()); + aux[2] = ':'; + aux[5] = ':'; + lcd->XString(OFFSETX, OFFSETY + 8*5, aux); // Cambiar + + // Se escribe el consejo en la parte inferior de la pantalla + lcd->XString(OFFSETX, HEIGHT - 8, advice); + + // transmit work screen to physical screen: + lcd->Flush(); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pantallas/ArchivoGuardado.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,38 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#ifndef ARCHIVOGUARDADO_H +#define ARCHIVOGUARDADO_H + +#include "Seleccion.h" +#include "FechaHora.h" +#include "doggy.h" + +#define MAXCARACTER 22 // Número máximo de caracteres de cada elemento +#define OFFSETX 4 // Espacio en pixeles que se deja antes de escribir una linea de caracteres +#define OFFSETXTITLES 16 // Espacio en pixeles que se deja antes de escribir una linea de caracteres +#define OFFSETY 4 // Espacio en pixeles que se deja antes de escribir una linea de caracteres + +// Lista de elementos seleccionables. Tamaño de caracteres 8. +class ArchivoGuardado: public Seleccion{ + public: + ArchivoGuardado(char nextScreen[], char newAdvice[], char newnameTitle[], char newdateTitle[], char newtimeTitle[]); + virtual void initialize(DogMLCD* lcd); + + virtual void button5pressed(DogMLCD* lcd); // Esta función se llama cuando el botón central es pulsado, definirla para añadir funcionalidades + + void setName(char newName[]); + void setDate(char newDate[]); + void setTime(char newTime[]); + + private: + char nextScreenID[NCARSCREEN]; + char advice[MAXCARACTER + 10]; + char nameTitle[MAXCARACTER]; + char dateTitle[MAXCARACTER]; + char timeTitle[MAXCARACTER]; + + +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pantallas/AutoCalibracion.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,506 @@ +#include "AutoCalibracion.h" +/// ACELEROMETRO DIGITAL/// +extern KXR94 kionix; + +extern ScreenManager SC; +extern SistemaArchivos SA; +extern Configuracion config; +extern MSCFileSystem msc; + +extern DigitalIn boton5; +extern DigitalIn boton6; + +void AutoCalibracion::initialize(DogMLCD* lcd){ + pasoCalibracion = 0; // Pantalla de introduccion + + mediaXpos = 0; + mediaYpos = 0; + mediaZpos = 0; + mediaXneg = 0; + mediaYneg = 0; + mediaZneg = 0; + + // Inicilización de las variables + pulsado5 = false; + pulsado6 = false; + leyendoDatos = false; + + char idioma[16]; + // Se selecciona el idioma + config.getIdioma(idioma); + + // select font to use: + lcd->XFont = xfont_11; + + // output title text + if(strcmp(idioma, "spanish") == 0){ + lcd->XString( OFFSETX, OFFSETY, "Autocalibraci\242n"); + }else if(strcmp(idioma, "english") == 0){ + lcd->XString( OFFSETX, OFFSETY, "Autocalibration"); + } + + lcd->XFont = xfont_8; + + if(strcmp(idioma, "spanish") == 0){ + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG, "Siga los pasos siguientes"); + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG + 8, "para calibrar el"); + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG + 8*2, "dispositivo."); + }else if(strcmp(idioma, "english") == 0){ + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG, "Follow next steps to"); + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG + 8, "calibrate the device."); + } + + // transmit work screen to physical screen: + lcd->Flush(); + + // Se prepara el acelerómetro + kionix.AcelerometroWakeUp(); + // select font to use: + lcd->XFont = xfont_11; + + // output msg2 text + if(strcmp(idioma, "spanish") == 0){ + lcd->XString( OFFSETX, HEIGHT -1 - 18, "OK para continuar."); + }else if(strcmp(idioma, "english") == 0){ + lcd->XString( OFFSETX, HEIGHT -1 - 18, "OK to continue."); + } + + // transmit work screen to physical screen: + lcd->Flush(); +} + +void AutoCalibracion::update(DogMLCD* lcd){ + // Si se están leyendo datos se comprueba si se ha tomado el número de medidas deseadas + if(leyendoDatos){ + if(datosCapturados >= NDATOSPASO){ // Se ha acabado la lectura de los datos + // Se para la lectura de datos + tickerLectura.detach(); + + leyendoDatos = false; + + // Se guarda el valor de la media en su variable correspondiente + // Dependiendo del paso nos interesa sumar un eje en concreto + switch(pasoCalibracion){ + case 1: + mediaXpos = mediaAux/NDATOSPASO; + //mediaZpos = mediaAux; + break; + + case 2: + mediaXneg = mediaAux/NDATOSPASO; + //mediaXneg = mediaAux; + break; + + case 3: + mediaYneg = mediaAux/NDATOSPASO; + //mediaXpos = mediaAux; + break; + + case 4: + mediaYpos = mediaAux/NDATOSPASO; + //mediaYpos = mediaAux; + break; + + case 5: + mediaZpos = mediaAux/NDATOSPASO; + //mediaYneg = mediaAux; + break; + + case 6: + mediaZneg = mediaAux/NDATOSPASO; + //mediaZneg = mediaAux; + + // Una vez terminado el paso 6 ya se tienen los datos suficientes para calcular los parámetros de calibración + // Primero se calculan los factores de conversión a unidades físicas + float newKX; + float newKY; + float newKZ; + if(mediaXpos >= mediaXneg){ + newKX = (2.0*ACELGRAVEDAD)/(mediaXpos - mediaXneg); + }else{ + newKX = (2.0*ACELGRAVEDAD)/(mediaXneg - mediaXpos); + } + + if(mediaYpos >= mediaYneg){ + newKY = (2.0*ACELGRAVEDAD)/(mediaYpos - mediaYneg); + }else{ + newKY = (2.0*ACELGRAVEDAD)/(mediaYneg - mediaYpos); + } + + if(mediaZpos >= mediaZneg){ + newKZ = (2.0*ACELGRAVEDAD)/(mediaZpos - mediaZneg); + }else{ + newKZ = (2.0*ACELGRAVEDAD)/(mediaZneg - mediaZpos); + } + + // Se calcula el offset de cada eje + float newAX; + float newAY; + float newAZ; + + //if(mediaXpos >= mediaXneg){ + //newAX = mediaXpos - (ACELGRAVEDAD/KX); + /*}else{ + newAX = mediaXneg - (ACELGRAVEDAD/KX); + }*/ + + //if(mediaYpos >= mediaYneg){ + //newAY = mediaYpos - (ACELGRAVEDAD/KY); + /*}else{ + newAY = mediaYneg - (ACELGRAVEDAD/KY); + }*/ + + //if(mediaZpos >= mediaZneg){ + //newAZ = mediaZpos - (ACELGRAVEDAD/KZ); + /*}else{ + newAZ = mediaZneg - (ACELGRAVEDAD/KZ); + }*/ + + newAX = (mediaXpos + mediaXneg)/2.0; + newAY = (mediaYpos + mediaYneg)/2.0; + newAZ = (mediaZpos + mediaZneg)/2.0; + + float param[] = {newAX, newAY, newAZ, newKX, newKY, newKZ}; + + /*FILE* fp = fopen("/local/prueba1.txt","w"); + fprintf(fp, "%f\n%f\n\n%f\n%f\n\n%f\n%f\n\n%f\n%f\n%f\n\n%f\n%f\n%f\n", mediaYpos, mediaYneg, mediaXpos, mediaXneg, mediaZneg, mediaZpos, newAX, newAY, newAZ, newKX, newKY, newKZ); + fclose(fp);*/ + + // Se guardan los nuevos valores de calibración + ParametrosCalibracion::saveValores(param); + + break; + } + + pasoCalibracion++; + + // Se pinta la siguiente pantalla + lcd->Flush(); + + } + } + + // Botón OK + if(boton5 == 1){ + pulsado5 = true; + }else{ + if(pulsado5 == true){ // El boton ha sido pulsado + pulsado5 = false; + if(!leyendoDatos){ // Si el viaje no habia comenzado + leyendoDatos = true; + + // Se borra la pantalla + lcd->Clear(); + + char idioma[16]; + // Se selecciona el idioma + config.getIdioma(idioma); + + // select font to use: + lcd->XFont = xfont_11; + + // Algunos mensajes son comunes para todos los pasos + // output msg2 text + if(strcmp(idioma, "spanish") == 0){ + lcd->XString( OFFSETX, HEIGHT -1 - 18, "OK para continuar."); + }else if(strcmp(idioma, "english") == 0){ + lcd->XString( OFFSETX, HEIGHT -1 - 18, "OK to continue."); + } + + // Dependiendo del paso nos interesa sumar un eje en concreto + switch(pasoCalibracion){ + case 0: + // Se pasa directamente al Paso 1 + leyendoDatos = false; + + // select font to use: + lcd->XFont = xfont_11; + + // output title text + if(strcmp(idioma, "spanish") == 0){ + lcd->XString( OFFSETX, OFFSETY, "Paso 1"); + }else if(strcmp(idioma, "english") == 0){ + lcd->XString( OFFSETX, OFFSETY, "Step 1"); + } + + lcd->XFont = xfont_8; + + if(strcmp(idioma, "spanish") == 0){ + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG, "Coloque la cara derecha del"); + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG + 8, "dispositivo sobre una"); + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG + 8*2, "superficie plana."); + }else if(strcmp(idioma, "english") == 0){ + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG, "Place the right side of the"); + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG + 8, "device on a flat surface."); + } + + // Se prepara el acelerómetro + kionix.AcelerometroWakeUp(); + + // Se pinta la siguiente pantalla + lcd->Flush(); + pasoCalibracion++; + break; + + case 1: + // Lectura de datos del paso 1, se prepara la pantalla del paso 2 + + // select font to use: + lcd->XFont = xfont_11; + + // output title text + if(strcmp(idioma, "spanish") == 0){ + lcd->XString( OFFSETX, OFFSETY, "Paso 2"); + }else if(strcmp(idioma, "english") == 0){ + lcd->XString( OFFSETX, OFFSETY, "Step 2"); + } + + lcd->XFont = xfont_8; + + if(strcmp(idioma, "spanish") == 0){ + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG, "Coloque la cara izquierda del"); + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG + 8, "dispositivo sobre una"); + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG + 8*2, "superficie plana."); + }else if(strcmp(idioma, "english") == 0){ + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG, "Place the left side of the"); + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG + 8, "device on a flat surface."); + } + + mediaAux = 0; + datosCapturados = 0; + + // Se espera unos segundos antes de comenzar a tomar medidas para asegurar las vibraciones debidas + // a la pulsación del botón no interfieren en las medidas + wait(OFFSETTIEMPO); + // Se comienza a leer el acelerómetro + tickerLectura.attach_us(this, &AutoCalibracion::LeeAcelerometro, USENTREDATOS); + + break; + + case 2: + + // Lectura de datos del paso 1, se prepara la pantalla del paso 3 + + // select font to use: + lcd->XFont = xfont_11; + + // output title text + if(strcmp(idioma, "spanish") == 0){ + lcd->XString( OFFSETX, OFFSETY, "Paso 3"); + }else if(strcmp(idioma, "english") == 0){ + lcd->XString( OFFSETX, OFFSETY, "Step 3"); + } + + lcd->XFont = xfont_8; + + if(strcmp(idioma, "spanish") == 0){ + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG, "Coloque la cara superior del"); + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG + 8, "dispositivo sobre una"); + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG + 8*2, "superficie plana."); + }else if(strcmp(idioma, "english") == 0){ + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG, "Place the top side of the"); + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG + 8, "device on a flat surface."); + } + + mediaAux = 0; + datosCapturados = 0; + + // Se espera unos segundos antes de comenzar a tomar medidas para asegurar las vibraciones debidas + // a la pulsación del botón no interfieren en las medidas + wait(OFFSETTIEMPO); + // Se comienza a leer el acelerómetro + tickerLectura.attach_us(this, &AutoCalibracion::LeeAcelerometro, USENTREDATOS); + + break; + + case 3: + + // Lectura de datos del paso 1, se prepara la pantalla del paso 4 + + // select font to use: + lcd->XFont = xfont_11; + + // output title text + if(strcmp(idioma, "spanish") == 0){ + lcd->XString( OFFSETX, OFFSETY, "Paso 4"); + }else if(strcmp(idioma, "english") == 0){ + lcd->XString( OFFSETX, OFFSETY, "Step 4"); + } + + lcd->XFont = xfont_8; + + if(strcmp(idioma, "spanish") == 0){ + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG, "Coloque la cara inferior del"); + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG + 8, "dispositivo sobre una"); + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG + 8*2, "superficie plana."); + }else if(strcmp(idioma, "english") == 0){ + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG, "Place the bottom side of the"); + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG + 8, "device on a flat surface."); + } + + mediaAux = 0; + datosCapturados = 0; + + // Se espera unos segundos antes de comenzar a tomar medidas para asegurar las vibraciones debidas + // a la pulsación del botón no interfieren en las medidas + wait(OFFSETTIEMPO); + // Se comienza a leer el acelerómetro + tickerLectura.attach_us(this, &AutoCalibracion::LeeAcelerometro, USENTREDATOS); + + break; + + case 4: + + // Lectura de datos del paso 1, se prepara la pantalla del paso 5 + + // select font to use: + lcd->XFont = xfont_11; + + // output title text + if(strcmp(idioma, "spanish") == 0){ + lcd->XString( OFFSETX, OFFSETY, "Paso 5"); + }else if(strcmp(idioma, "english") == 0){ + lcd->XString( OFFSETX, OFFSETY, "Step 5"); + } + + lcd->XFont = xfont_8; + + if(strcmp(idioma, "spanish") == 0){ + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG, "Coloque la cara frontal del"); + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG + 8, "dispositivo sobre una"); + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG + 8*2, "superficie plana."); + }else if(strcmp(idioma, "english") == 0){ + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG, "Place the front side of the"); + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG + 8, "device on a flat surface."); + } + + mediaAux = 0; + datosCapturados = 0; + + // Se espera unos segundos antes de comenzar a tomar medidas para asegurar las vibraciones debidas + // a la pulsación del botón no interfieren en las medidas + wait(OFFSETTIEMPO); + // Se comienza a leer el acelerómetro + tickerLectura.attach_us(this, &AutoCalibracion::LeeAcelerometro, USENTREDATOS); + + break; + + case 5: + + // Lectura de datos del paso 1, se prepara la pantalla del paso 6 + + // select font to use: + lcd->XFont = xfont_11; + + // output title text + if(strcmp(idioma, "spanish") == 0){ + lcd->XString( OFFSETX, OFFSETY, "Paso 6"); + }else if(strcmp(idioma, "english") == 0){ + lcd->XString( OFFSETX, OFFSETY, "Step 6"); + } + + lcd->XFont = xfont_8; + + if(strcmp(idioma, "spanish") == 0){ + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG, "Coloque la cara trasera del"); + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG + 8, "dispositivo sobre una"); + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG + 8*2, "superficie plana."); + }else if(strcmp(idioma, "english") == 0){ + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG, "Place the rear side of the"); + lcd->XString( OFFSETX, OFFSETY + OFFSETMSG + 8, "device on a flat surface."); + } + + mediaAux = 0; + datosCapturados = 0; + + // Se espera unos segundos antes de comenzar a tomar medidas para asegurar las vibraciones debidas + // a la pulsación del botón no interfieren en las medidas + wait(OFFSETTIEMPO*2); + // Se comienza a leer el acelerómetro + tickerLectura.attach_us(this, &AutoCalibracion::LeeAcelerometro, USENTREDATOS); + + break; + + case 6: + + // select font to use: + lcd->XFont = xfont_11; + + // output title text + if(strcmp(idioma, "spanish") == 0){ + lcd->XString( OFFSETX + 28, OFFSETY + 8, "Calibraci\242n"); + lcd->XString( OFFSETX + 28, OFFSETY + 8 + 12, "completada."); + }else if(strcmp(idioma, "english") == 0){ + lcd->XString( OFFSETX + 28, OFFSETY + 8, "Calibration"); + lcd->XString( OFFSETX + 28, OFFSETY + 8 + 12, "completed."); + } + + mediaAux = 0; + datosCapturados = 0; + + // Se espera unos segundos antes de comenzar a tomar medidas para asegurar las vibraciones debidas + // a la pulsación del botón no interfieren en las medidas + wait(OFFSETTIEMPO); + // Se comienza a leer el acelerómetro + tickerLectura.attach_us(this, &AutoCalibracion::LeeAcelerometro, USENTREDATOS); + + break; + + case 7: + // Se duerme el acelerómetro + kionix.AcelerometroSleep(); + // Se vuelve a la pantalla de configuración + SC.changeScreen("configuracion"); + break; + } + } + } + } + + // Botón atrás + if(boton6 == 1){ + pulsado6 = true; + }else{ + if(pulsado6 == true){ + pulsado6 = false; + // En cualquier momento puede volverse atrás (al menú de configuración) parando el proceso actual y perdiendo todos los datos que se hayan guardado de la calibración hasta el mommento, teniendo que repetir el proceso + // Se duerme el acelerómetro + kionix.AcelerometroSleep(); + SC.changeScreen("configuracion"); + } + } +} + +void AutoCalibracion::LeeAcelerometro() +{ + kionix.ReadAccels_KXR94(readings); + + // Dependiendo del paso nos interesa sumar un eje en concreto + switch(pasoCalibracion){ + case 1: + mediaAux += readings[0]; + break; + + case 2: + mediaAux += readings[0]; + break; + + case 3: + mediaAux += readings[1]; + break; + + case 4: + mediaAux += readings[1]; + break; + + case 5: + mediaAux += readings[2]; + break; + + case 6: + mediaAux += readings[2]; + break; + } + + datosCapturados++; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pantallas/AutoCalibracion.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,53 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#ifndef AUTOCALIBRACION_H +#define AUTOCALIBRACION_H + +#include "mbed.h" +#include "SistemaArchivos.h" +#include "ScreenManager.h" +#include "MSCFileSystem.h" +#include "Configuracion.h" +#include "KXR94.h" +#include "Buffering.h" +#include <stdlib.h> +#include "ParametrosCalibracion.h" + +#define MAXCAR 32 +#define OFFSETX 4 // Espacio en pixeles que se deja antes de escribir una linea de caracteres +#define OFFSETY 2 // Espacio en pixeles que se deja antes de escribir una linea de caracteres en la parte superior +#define OFFSETMSG 12 + +#define OFFSETTIEMPO 2 // Tiempo que se espera desde que se pulsa el botón OK hasta que se comienza a tomar medidas (en segundos) +#define NDATOSPASO 1000 // Número de datos que se leerán en cada paso para hacer las medias +#define USENTREDATOS 1000 // Tiempo entre la lectura de cada dato en microsegundos + +#define ACELGRAVEDAD 9.81 + +class AutoCalibracion : public Screen { + public: + virtual void initialize(DogMLCD* lcd); + virtual void update(DogMLCD* lcd); + + private: + bool pulsado5; + bool pulsado6; + bool leyendoDatos; // Indica si el viaje está o no en proceso + + char pasoCalibracion; // Paso actual de los 7 pasos para calibrar el dispositivo + + int readings[3]; //Lectura aceleraciones sensor digital + float mediaXpos, mediaYpos, mediaZpos, mediaXneg, mediaYneg, mediaZneg; // Variables que guardan las medias medidas en cada paso + int datosCapturados; // Numero de datos que se han leído en cada paso + float mediaAux; // En esta variable se va calculando la media a medida que llegan los datos + + float aXr, aYr, aZr; //Tiempo y medidas de aceleracion leidos del buffer + //unsigned int contDatos; //Contador de datos + unsigned int ContadorDatos; + + Ticker tickerLectura; + void LeeAcelerometro(); +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pantallas/Configuracion/FormaSelec.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,24 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#include "FormaSelec.h" + +extern SelecManager SM; +extern Configuracion config; + +void FormaSelec::button5pressed(DogMLCD* lcd){ + // Se cambia la forma de selección actual y se guarda en la configuración + switch(getSelect()){ + // sombreado + case 0: + config.setFormaSeleccion("shading"); + SM.setInverterSelection(); + break; + // Encuadrado + case 1: + config.setFormaSeleccion("framing"); + SM.setRectSelection(); + break; + } + ListaSelec::button5pressed(lcd); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pantallas/Configuracion/FormaSelec.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,17 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#ifndef FORMASELEC_H +#define FORMASELEC_H + +#include "SelecManager.h" +#include "ListaSelec.h" +#include "Configuracion.h" + +// Lista de elementos seleccionables. Tamaño de caracteres 8. +class FormaSelec: public ListaSelec{ + public: + virtual void button5pressed(DogMLCD* lcd); +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pantallas/Configuracion/IdiomaSelec.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,24 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#include "IdiomaSelec.h" + +extern ScreenManager SC; +extern Configuracion config; + +void IdiomaSelec::button5pressed(DogMLCD* lcd){ + // Se cambia el idioma actual y se guarda tambien en el fichero de configuracion + switch(getSelect()){ + // Español + case 0: + config.setIdioma("spanish"); + SC.selectGroup(0); + break; + // Inglés + case 1: + config.setIdioma("english"); + SC.selectGroup(1); + break; + } + ListaSelec::button5pressed(lcd); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pantallas/Configuracion/IdiomaSelec.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,16 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#ifndef IDIOMASELEC_H +#define IDIOMASELEC_H + +#include "ListaSelec.h" +#include "Configuracion.h" + +// Lista de elementos seleccionables. Tamaño de caracteres 8. +class IdiomaSelec: public ListaSelec{ + public: + virtual void button5pressed(DogMLCD* lcd); +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pantallas/Configuracion/RestaurarValores.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,30 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#include "RestaurarValores.h" + +extern Configuracion config; + +RestaurarValores::RestaurarValores(char message[]){ + strcpy(advice, message); +} + +void RestaurarValores::initialize(DogMLCD* lcd){ + lcd->XFont = xfont_8; + lcd->XString(OFFSETX, OFFSETY, advice); + Menu::initialize(lcd); +} + +void RestaurarValores::button5pressed(DogMLCD* lcd){ + // Se cambia el idioma actual y se guarda tambien en el fichero de configuracion + switch(getSelect()){ + // No se restaura la configuración + case 0: + break; + // Se restaura La configuración + case 1: + config.restoreSettings(); + break; + } + Menu::button5pressed(lcd); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pantallas/Configuracion/RestaurarValores.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,26 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#ifndef RESTAURARVALORES_H +#define RESTAURARVALORES_H + +#define OFFSETX 4 // Espacio en pixeles que se deja antes de escribir una linea de caracteres +#define OFFSETY 4 // Espacio en pixeles que se deja antes de escribir una linea de caracteres en la parte superior + +#include "Menu.h" +#include "Configuracion.h" +#include <string.h> + +// Lista de elementos seleccionables. Tamaño de caracteres 8. +class RestaurarValores: public Menu{ + public: + RestaurarValores(char message[]); + virtual void initialize(DogMLCD* lcd); + virtual void button5pressed(DogMLCD* lcd); + +private: + char advice[64]; + +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pantallas/Configuracion/VelAdquisicionSel.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,21 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#include "VelAdquisicionSel.h" + +extern Configuracion config; + +void VelAdquisicionSel::button5pressed(DogMLCD* lcd){ + // Se cambia el idioma actual y se guarda tambien en el fichero de configuracion + switch(getSelect()){ + // 1000 Hz + case 0: + config.setVelocidadAdquision(1000); + break; + // 320 Hz + case 1: + config.setVelocidadAdquision(320); + break; + } + ListaSelec::button5pressed(lcd); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pantallas/Configuracion/VelAdquisicionSel.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,16 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#ifndef VELADQUISICIONSEL_H +#define VELADQUISICIONSEL_H + +#include "ListaSelec.h" +#include "Configuracion.h" + +// Lista de elementos seleccionables. Tamaño de caracteres 8. +class VelAdquisicionSel: public ListaSelec{ + public: + virtual void button5pressed(DogMLCD* lcd); +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pantallas/FechaHoraConf.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,479 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#include "FechaHoraConf.h" + +extern ScreenManager SC; +extern FechaHora FH; + +extern DigitalIn boton1; +extern DigitalIn boton2; +extern DigitalIn boton3; +extern DigitalIn boton4; +extern DigitalIn boton5; + +extern DigitalOut myled; + +extern Timer t; + +FechaHoraConf::FechaHoraConf(char newAdvice[], char newAdvice2[], char newAdvice3[], char newdateTitle[], char newtimeTitle[]){ + strcpy(advice, newAdvice); + strcpy(advice2, newAdvice2); + strcpy(advice3, newAdvice3); + + strcpy(dateTitle, newdateTitle); + strcpy(timeTitle, newtimeTitle); +} + +// Tecla arriba +void FechaHoraConf::button1pressed(DogMLCD* lcd){ + char aux[5]; + switch(getSelect()){ + // día + case 0: + // Dependiendo del mes el límite del dia es diferente + if(FH.getNmonth() == 2 && FH.getNday()+1 > 28){ // Febrero + FH.setNday(1); + }else if((FH.getNmonth() == 1 || FH.getNmonth() == 3 || FH.getNmonth() == 5 || FH.getNmonth() == 7 || FH.getNmonth() == 8 || FH.getNmonth() == 10 || FH.getNmonth() == 12) && FH.getNday()+1 > 31){ // Meses con 31 días + FH.setNday(1); + }else if((FH.getNmonth() == 4 || FH.getNmonth() == 6 || FH.getNmonth() == 9 || FH.getNmonth() == 11) && FH.getNday()+1 > 30){ // Meses con 31 días + FH.setNday(1); + }else{ // sino se aumenta un día + FH.setNday(FH.getNday()+1); + } + + // Se actualiza el tiempo bruto + FH.updateRawTime(); + + // Se cambia el texto de pantalla + FH.getDay(aux); + aux[2] = '\0'; + changeElementText(aux, getSelect(), lcd); + + // Se redibuja la selección + dibujarSeleccion(getSelect(), lcd); + break; + // mes + case 1: + // Si el mes es mayor que 12 se devuelve al 1 + if((FH.getNmonth()+1) > 12){ + FH.setNmonth(1); + }else{ // sino se aumenta un mes + FH.setNmonth(FH.getNmonth()+1); + } + + // Se actualiza el tiempo bruto + FH.updateRawTime(); + + // Se cambia el texto de pantalla + FH.getMonth(aux); + aux[2] = '\0'; + changeElementText(aux, getSelect(), lcd); + + // Se redibuja la selección + dibujarSeleccion(getSelect(), lcd); + break; + // año + case 2: + // Si el año es mayor que 1099(2999) se devuelve al 0(1900) + if((FH.getNyear()+1) > 1099){ + FH.setNyear(0); + }else{ // sino se aumenta un año + FH.setNyear(FH.getNyear()+1); + } + + // Se actualiza el tiempo bruto + FH.updateRawTime(); + + // Se cambia el texto de pantalla + FH.getYear(aux); + aux[4] = '\0'; + changeElementText(aux, getSelect(), lcd); + + // Se redibuja la selección + dibujarSeleccion(getSelect(), lcd); + break; + // hora + case 3: + // Si la hora es mayor que 23 se devuelve al 0 + if((FH.getNhour()+1) > 23){ + FH.setNhour(0); + }else{ // sino se aumenta una hora + FH.setNhour(FH.getNhour()+1); + } + + // Se actualiza el tiempo bruto + FH.updateRawTime(); + + // Se cambia el texto de pantalla + FH.getHour(aux); + aux[2] = '\0'; + changeElementText(aux, getSelect(), lcd); + + // Se redibuja la selección + dibujarSeleccion(getSelect(), lcd); + break; + // minuto + case 4: + // Si el minuto es mayor que 59 se devuelve al 0 + if((FH.getNminute()+1) > 59){ + FH.setNminute(0); + }else{ // sino se aumenta un minuto + FH.setNminute(FH.getNminute()+1); + } + + // Se actualiza el tiempo bruto + FH.updateRawTime(); + + // Se cambia el texto de pantalla + FH.getMinute(aux); + aux[2] = '\0'; + changeElementText(aux, getSelect(), lcd); + + // Se redibuja la selección + dibujarSeleccion(getSelect(), lcd); + break; + // segundo + case 5: + // Si el segundo es mayor que 59 se devuelve al 0 + if((FH.getNsecond()+1) > 59){ + FH.setNsecond(0); + }else{ // sino se aumenta un segundo + FH.setNsecond(FH.getNsecond()+1); + } + + // Se actualiza el tiempo bruto + FH.updateRawTime(); + + // Se cambia el texto de pantalla + FH.getSecond(aux); + aux[2] = '\0'; + changeElementText(aux, getSelect(), lcd); + + // Se redibuja la selección + dibujarSeleccion(getSelect(), lcd); + break; + } + // transmit work screen to physical screen: + lcd->Flush(); +} + +// Tecla abajo +void FechaHoraConf::button4pressed(DogMLCD* lcd){ + char aux[5]; + switch(getSelect()){ + // día + case 0: + // Dependiendo del mes el límite del dia es diferente + if(FH.getNmonth() == 2 && FH.getNday()-1 < 0){ // Febrero + FH.setNday(28); + }else if((FH.getNmonth() == 1 || FH.getNmonth() == 3 || FH.getNmonth() == 5 || FH.getNmonth() == 7 || FH.getNmonth() == 8 || FH.getNmonth() == 10 || FH.getNmonth() == 12) && FH.getNday()-1 < 0){ // Meses con 31 días + FH.setNday(31); + }else if((FH.getNmonth() == 4 || FH.getNmonth() == 6 || FH.getNmonth() == 9 || FH.getNmonth() == 11) && FH.getNday()-1 < 0){ // Meses con 31 días + FH.setNday(30); + }else{ // sino se aumenta un día + FH.setNday(FH.getNday()-1); + } + + // Se actualiza el tiempo bruto + FH.updateRawTime(); + + // Se cambia el texto de pantalla + FH.getDay(aux); + aux[2] = '\0'; + changeElementText(aux, getSelect(), lcd); + + // Se redibuja la selección + dibujarSeleccion(getSelect(), lcd); + break; + // mes + case 1: + // Si el mes es mayor que 12 se devuelve al 1 + if((FH.getNmonth()-1) < 1){ + FH.setNmonth(12); + }else{ // sino se aumenta un mes + FH.setNmonth(FH.getNmonth()-1); + } + + // Se actualiza el tiempo bruto + FH.updateRawTime(); + + // Se cambia el texto de pantalla + FH.getMonth(aux); + aux[2] = '\0'; + changeElementText(aux, getSelect(), lcd); + + // Se redibuja la selección + dibujarSeleccion(getSelect(), lcd); + break; + // año + case 2: + // Si el año es mayor que 1099(2999) se devuelve al 0(1900) + if((FH.getNyear()-1) < 0){ + FH.setNyear(1099); + }else{ // sino se aumenta un año + FH.setNyear(FH.getNyear()-1); + } + + // Se actualiza el tiempo bruto + FH.updateRawTime(); + + // Se cambia el texto de pantalla + FH.getYear(aux); + aux[4] = '\0'; + changeElementText(aux, getSelect(), lcd); + + // Se redibuja la selección + dibujarSeleccion(getSelect(), lcd); + break; + // hora + case 3: + // Si la hora es mayor que 23 se devuelve al 0 + if((FH.getNhour()-1) < 0){ + FH.setNhour(23); + }else{ // sino se aumenta una hora + FH.setNhour(FH.getNhour()-1); + } + + // Se actualiza el tiempo bruto + FH.updateRawTime(); + + // Se cambia el texto de pantalla + FH.getHour(aux); + aux[2] = '\0'; + changeElementText(aux, getSelect(), lcd); + + // Se redibuja la selección + dibujarSeleccion(getSelect(), lcd); + break; + // minuto + case 4: + // Si el minuto es mayor que 59 se devuelve al 0 + if((FH.getNminute()-1) < 0){ + FH.setNminute(59); + }else{ // sino se aumenta un minuto + FH.setNminute(FH.getNminute()-1); + } + + // Se actualiza el tiempo bruto + FH.updateRawTime(); + + // Se cambia el texto de pantalla + FH.getMinute(aux); + aux[2] = '\0'; + changeElementText(aux, getSelect(), lcd); + + // Se redibuja la selección + dibujarSeleccion(getSelect(), lcd); + break; + // segundo + case 5: + // Si el segundo es mayor que 59 se devuelve al 0 + if((FH.getNsecond()-1) < 0){ + FH.setNsecond(59); + }else{ // sino se aumenta un segundo + FH.setNsecond(FH.getNsecond()-1); + } + + // Se actualiza el tiempo bruto + FH.updateRawTime(); + + // Se cambia el texto de pantalla + FH.getSecond(aux); + aux[2] = '\0'; + changeElementText(aux, getSelect(), lcd); + + // Se redibuja la selección + dibujarSeleccion(getSelect(), lcd); + break; + } + // transmit work screen to physical screen: + lcd->Flush(); +} + +// Tecla izquierda +void FechaHoraConf::button2pressed(DogMLCD* lcd){ + // Sólo se puede mover la seleccón a la izquierda si no se está en el elemento 0 + if(getSelect() > 0){ + // Se deselecciona el elemento seleccionado actualmente + borrarSeleccion(getSelect(), lcd); + setSelect(getSelect()-1); + // Se pinta la nueva selección + dibujarSeleccion(getSelect(), lcd); + + // transmit work screen to physical screen: + lcd->Flush(); + } +} + +// Tecla derecha +void FechaHoraConf::button3pressed(DogMLCD* lcd){ + // Sólo se puede mover la seleccón a la derecha si no se está en el elemento 5 + if(getSelect() < 5){ + // Se deselecciona el elemento seleccionado actualmente + borrarSeleccion(getSelect(), lcd); + setSelect(getSelect()+1); + // Se pinta la nueva selección + dibujarSeleccion(getSelect(), lcd); + + // transmit work screen to physical screen: + lcd->Flush(); + } +} + +void FechaHoraConf::button5pressed(DogMLCD* lcd){ + +} + +void FechaHoraConf::initialize(DogMLCD* lcd){ + // Se borran los elementos anteriores + borrarElementos(); + + // select font to use: + lcd->XFont = xfont_8; + + FH.update(); // Se actualiza la fecha y hora + // Se inicia el temporizador que se usará para actualizar la hora + t.reset(); + t.start(); + + // Se escribe el título de fecha + lcd->XString(OFFSETXTITLES, OFFSETY + 8*0, dateTitle); + + // Se escribe el título de hora + lcd->XString(OFFSETXTITLES, OFFSETY + 8*2, timeTitle); + + char aux[5]; + + // Se añade el elemento día + FH.getDay(aux); + aux[2] = '\0'; + addElement(aux, OFFSETX, OFFSETY + 8*1); + + // Se añade el elemento mes + FH.getMonth(aux); + aux[2] = '\0'; + addElement(aux, OFFSETX+21, OFFSETY + 8*1); + + // Se añade el elemento año + FH.getYear(aux); + aux[4] = '\0'; + addElement(aux, OFFSETX+42, OFFSETY + 8*1); + + // Se añade el elemento hora + FH.getHour(aux); + aux[2] = '\0'; + addElement(aux, OFFSETX, OFFSETY + 8*3); + + // Se añade el elemento minuto + FH.getMinute(aux); + aux[2] = '\0'; + addElement(aux, OFFSETX+21, OFFSETY + 8*3); + + // Se añade el elemento segundo + FH.getSecond(aux); + aux[2] = '\0'; + addElement(aux, OFFSETX+42, OFFSETY + 8*3); + + // Se muestran dos puntos para separar cada uno de los valores + lcd->XString(20,OFFSETY + 8, ":"); + lcd->XString(41,OFFSETY + 8, ":"); + lcd->XString(20,OFFSETY + 8*3, ":"); + lcd->XString(41,OFFSETY + 8*3, ":"); + + // Se muestran todos los elementos + for(int i = 0; i < nElementos; i++){ + lcd->XString(elementPos[i][0], elementPos[i][1], element[i]); + } + + setSelect(0); + // Se dibuja la selección por defecto + dibujarSeleccion(getSelect(), lcd); + + // Se escribe el consejo en la parte inferior de la pantalla + lcd->XString(OFFSETX, HEIGHT - 8*3, advice); + lcd->XString(OFFSETX, HEIGHT - 8*2, advice2); + lcd->XString(OFFSETX, HEIGHT - 8, advice3); + + // transmit work screen to physical screen: + lcd->Flush(); +} + +void FechaHoraConf::dibujarSeleccion(char nElemento, DogMLCD* lcd){ + if(nElemento == 2){ // Si el elemento es el 2 (el del año) el recuadro de selección es más grande + drawSelection(elementPos[nElemento][0]-2, elementPos[nElemento][1]-2, ANCHOSELECCION4, ALTOSELECCION, lcd); + }else{ + drawSelection(elementPos[nElemento][0]-2, elementPos[nElemento][1]-2, ANCHOSELECCION2, ALTOSELECCION, lcd); + } +} + +void FechaHoraConf::borrarSeleccion(char nElemento, DogMLCD* lcd){ + if(nElemento == 2){ // Si el elemento es el 2 (el del año) el recuadro de selección es más grande + drawDeselection(elementPos[nElemento][0]-2, elementPos[nElemento][1]-2, ANCHOSELECCION4, ALTOSELECCION, lcd); + }else{ + drawDeselection(elementPos[nElemento][0]-2, elementPos[nElemento][1]-2, ANCHOSELECCION2, ALTOSELECCION, lcd); + } +} + +void FechaHoraConf::update(DogMLCD* lcd){ + // Si no se está en los segundos se actualiza cada segundo la hora + if(getSelect() < 5){ + if(t.read_ms() >= 1000){ + t.reset(); + t.start(); + // Se actualiza la hora + FH.update(); + + char aux[5]; + // Se cambian los valores de los segundos, los minutos y las horas + // Se añade el elemento hora + FH.getHour(aux); + aux[2] = '\0'; + changeElementText(aux, 3, lcd); + + // Se añade el elemento minuto + FH.getMinute(aux); + aux[2] = '\0'; + changeElementText(aux, 4, lcd); + + // Se añade el elemento segundo + FH.getSecond(aux); + aux[2] = '\0'; + changeElementText(aux, 5, lcd); + + // Si la seleccion estaba en alguno de estos elementos se ha borrado, así que se vuelve a pintar + if(getSelect() > 2){ + dibujarSeleccion(getSelect(), lcd); + } + + // transmit work screen to physical screen: + lcd->Flush(); + } + } + + // Se llama a la función padre + Seleccion::update(lcd); +} + +void FechaHoraConf::changeElementText(char newText[], int nElemento, DogMLCD* lcd){ + // Se borra valor actual + if(nElemento == 2){ // Si el elemento es el 2 (el del año) el recuadro de selección es más grande + lcd->Rect(elementPos[nElemento][0]-2, elementPos[nElemento][1]-2, elementPos[nElemento][0]-2 + ANCHOSELECCION4, elementPos[nElemento][1]-2 + ALTOSELECCION, DOGMLCD_full, wipe); + }else{ + lcd->Rect(elementPos[nElemento][0]-2, elementPos[nElemento][1]-2, elementPos[nElemento][0]-2 + ANCHOSELECCION2, elementPos[nElemento][1]-2 + ALTOSELECCION, DOGMLCD_full, wipe); + } + // Se actualiza el texto del elemento + strcpy(element[nElemento], newText); + + // Se pinta el nuevo texto + lcd->XString(elementPos[nElemento][0], elementPos[nElemento][1], element[nElemento]); +} + + +int FechaHoraConf::addElement(char text[], char posX, char posY){ + strcpy(element[nElementos], text); + elementPos[nElementos][0] = posX; + elementPos[nElementos][1] = posY; + nElementos++; + return nElementos - 1; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pantallas/FechaHoraConf.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,55 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#ifndef FECHAHORACONF_H +#define FECHAHORACONF_H + +#include "Seleccion.h" +#include "FechaHora.h" +#include "doggy.h" + +#define NELEMENTS 6 // Número de elementos seleccionables de esta pantalla + +#define MAXCARACTER 22 // Número máximo de caracteres de cada elemento +#define OFFSETX 4 // Espacio en pixeles que se deja antes de escribir una linea de caracteres +#define OFFSETXTITLES 16 // Espacio en pixeles que se deja antes de escribir una linea de caracteres +#define OFFSETY 4 // Espacio en pixeles que se deja antes de escribir una linea de caracteres + +#define ANCHOSELECCION2 16 // Ancho del recuadro de selección de dos caracteres +#define ANCHOSELECCION4 32 // Ancho del recuadro de selección de cuatro caracteres +#define ALTOSELECCION 9 // Alto del recuadro de selección + +// Lista de elementos seleccionables. Tamaño de caracteres 8. +class FechaHoraConf: public Seleccion{ + public: + FechaHoraConf(char newAdvice[], char newAdvice2[], char newAdvice3[], char newdateTitle[], char newtimeTitle[]); + virtual void initialize(DogMLCD* lcd); + virtual void update(DogMLCD* lcd); + + virtual void button1pressed(DogMLCD* lcd); // Esta función se llama cuando el botón superior es pulsado, definirla para añadir funcionalidades + virtual void button2pressed(DogMLCD* lcd); // Esta función se llama cuando el botón superior es pulsado, definirla para añadir funcionalidades + virtual void button3pressed(DogMLCD* lcd); // Esta función se llama cuando el botón superior es pulsado, definirla para añadir funcionalidades + virtual void button4pressed(DogMLCD* lcd); // Esta función se llama cuando el botón inferior es pulsado, definirla para añadir funcionalidades + virtual void button5pressed(DogMLCD* lcd); // Esta función se llama cuando el botón central es pulsado, definirla para añadir funcionalidades + + int addElement(char text[], char posX, char posY); // Añade un elemento seleccionable a la pantalla + void changeElementText(char newText[], int nElemento, DogMLCD* lcd); + + private: + + char element[NELEMENTS][5]; // Variable que guarda los elementos seleccionables de la pantalla + char elementPos[NELEMENTS][2]; // Guarda la posición de los elementos de la pantalla + + char advice[MAXCARACTER*3]; + char advice2[MAXCARACTER*2]; + char advice3[MAXCARACTER*2]; + char dateTitle[MAXCARACTER]; + char timeTitle[MAXCARACTER]; + + void dibujarSeleccion(char nElemento, DogMLCD* lcd); + void borrarSeleccion(char nElemento, DogMLCD* lcd); + + +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pantallas/GuardarOtroNombre.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,106 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#include "GuardarOtroNombre.h" + +extern FechaHora FH; +extern ScreenManager SC; +extern SistemaArchivos SA; +extern MSCFileSystem msc; +extern Teclado keyboard; + +extern Mensaje guardadoCorrect; +extern Mensaje guardadoCorrectEN; + +extern Mensaje nombreExistente; +extern Mensaje nombreExistenteEN; + +extern DigitalOut myled; + +GuardarOtroNombre::GuardarOtroNombre(char nextScreen[], char newAdvice[], char newWaitMsg[]):Mensaje(nextScreen, newAdvice){ + nombreAntiguo = NULL; + strcpy(waitMsg, newWaitMsg); +} + +void GuardarOtroNombre::setNombreAntiguo(char *oldName){ + nombreAntiguo = oldName; +} + +void GuardarOtroNombre::disableNombreAntiguo(){ + nombreAntiguo = NULL; +} + +void GuardarOtroNombre::initialize(DogMLCD* lcd){ + // select font to use: + lcd->XFont = xfont_11; + // Se pinta un mensaje de espera + lcd->XString(OFFSETX + 8, 23, waitMsg); + // Se envía a la pantalla física + lcd->Flush(); + // Se deja la pantalla en blanco para cuando se acabe de cambair de nombre el archivo + lcd->Clear(); + + // Se cambia el nombre del archivo del propio USB + char oldFile[64]; + char newName[64]; + char aux[64]; + + // Si el nombreAntiguo vale NULL se toma como nombre antiguo la última fecha y hora guardado + if(nombreAntiguo == NULL){ + strcpy(aux, FH.getFechaHora()); + strcpy(oldFile, "/usb/RAW"); + strcat(oldFile, aux); + strcat(oldFile, ".txt"); + }else{ + strcpy(oldFile, "/usb/"); + strcat(oldFile, nombreAntiguo); + strcat(oldFile, ".txt"); + } + + // Si el archivo no se puede cargar se pasa a la pantalla que avisa que el USB está lleno o desconectado + FILE* file; + file = fopen(oldFile, "r"); + if(file == NULL){ + SC.changeScreen("USBdesconectado"); + }else{ + // Se cierra el archivo + fclose(file); + // El nombre nuevo se toma de el texto introducido con el teclado + strcpy(aux, keyboard.getNombre()); + // Se comprueba si ya existe un fichero con este nombre + if(SA.alredyExist(aux)){ + // Se configura la pantalla siguiente según si se está guardan un viaje nuevo con otro nombre o se está cambiando el nombre a uno ya existente + if(nombreAntiguo != NULL){ // Se debe de volver a la pantalla de opciones del viaje + nombreExistente.setNextScreen("rOptions"); + nombreExistente.setBackScreen("rOptions"); + nombreExistenteEN.setNextScreen("rOptions"); + nombreExistenteEN.setBackScreen("rOptions"); + }else{ // Se debe volver a la pantalla de guardado de nuevo viaje + nombreExistente.setNextScreen("guardaViaje"); + nombreExistente.setBackScreen("guardaViaje"); + nombreExistenteEN.setNextScreen("guardaViaje"); + nombreExistenteEN.setBackScreen("guardaViaje"); + } + SC.changeScreen("alredyExist"); + }else{ + // Se va a guardar cno otro nombre el archivo asi que + if(nombreAntiguo != NULL){ + SA.renameRide(nombreAntiguo, aux); + }else{ // Se guarda el nuevo nombre del archivo en la lista de nombres de los viajes sólo si nombreAntiguo vale NULL + strcpy(newName, "/usb/"); + strcat(newName, aux); + strcat(newName, ".txt"); + SA.file_rename(oldFile, newName); + strcpy(newName, keyboard.getNombre()); + SA.addElement(newName); + } + + // Se muestra el mensaje de archivo guardado correctamente por pantalla + Mensaje::initialize(lcd); + } + } +} + +void GuardarOtroNombre::button5pressed(DogMLCD* lcd){ + Mensaje::button5pressed(lcd); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pantallas/GuardarOtroNombre.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,33 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#ifndef GUARDAROTRONOMBRE_H +#define GUARDAROTRONOMBRE_H + +#include "Mensaje.h" +#include "SistemaArchivos.h" +#include "MSCFileSystem.h" +#include "ScreenManager.h" +#include "FechaHora.h" +#include "Teclado.h" + +// Lista de elementos seleccionables. Tamaño de caracteres 8. +class GuardarOtroNombre: public Mensaje{ + public: + GuardarOtroNombre(char nextScreen[], char newAdvice[], char newWaitMsg[]); + + virtual void initialize(DogMLCD* lcd); + + virtual void button5pressed(DogMLCD* lcd); + + void setNombreAntiguo(char *oldName); // Configura el nombre antiguo del archivo al que se le va a cambiar el nombre + // si vale NULL se considera que el nombre antiguo es el guardado por el sistema de fecha y hora (nombres por defecto) + void disableNombreAntiguo(); // Pone nombre antiguo a NULL + + private: + + char *nombreAntiguo; + char waitMsg[MAXCARACTER]; +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pantallas/GuardarViaje.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,62 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#include "GuardarViaje.h" + +extern FechaHora FH; +extern ScreenManager SC; +extern SistemaArchivos SA; +extern MSCFileSystem msc; +extern Teclado keyboard; + +extern GuardarOtroNombre guardadoCorrect; +extern GuardarOtroNombre guardadoCorrectEN; + +extern DigitalOut myled; + +void GuardarViaje::button5pressed(DogMLCD* lcd){ + bool llamarRaiz = true; // Se usa para llamar o no a la función padre (para controlar los cambios de pantalla) + // Se cambia el idioma actual y se guarda tambien en el fichero de configuracion + switch(getSelect()){ + char fileName[64]; + char auxTime[64]; + // Volver al menú + case 0: + // Se guarda el nombre del archivo en la lista de nombres de los viajes + strcpy(auxTime, FH.getFechaHora()); + strcpy(fileName, "RAW"); + strcat(fileName, auxTime); + SA.addElement(fileName); + break; + + // Cambiar nombre + case 1: + guardadoCorrect.setNextScreen("menu"); + guardadoCorrectEN.setNextScreen("menu"); + guardadoCorrect.setBackScreen("menu"); + guardadoCorrectEN.setBackScreen("menu"); + guardadoCorrect.disableNombreAntiguo(); + guardadoCorrectEN.disableNombreAntiguo(); + keyboard.setBackScreen("guardaViaje"); + keyboard.setNextScreen("fileSaved"); + break; + // Borrar el archivo + case 2: + llamarRaiz = false; + // Se borrar el archivo del último viaje + strcpy(auxTime, FH.getFechaHora()); + strcpy(fileName, "/usb/RAW"); + strcat(fileName, auxTime); + strcat(fileName, ".txt"); + + if(remove(fileName) != 0){ // Si no se pudo borrar se avisa por pantalla de USB + SC.changeScreen("USBdesconectado"); + }else{ + SC.changeScreen("archivoBorrado"); + } + break; + } + if(llamarRaiz){ + Menu::button5pressed(lcd); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pantallas/GuardarViaje.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,21 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#ifndef GUARDARVIAJE_H +#define GUARDARVIAJE_H + +#include "Menu.h" +#include "SistemaArchivos.h" +#include "MSCFileSystem.h" +#include "ScreenManager.h" +#include "FechaHora.h" +#include "Teclado.h" +#include "GuardarOtroNombre.h" + +// Lista de elementos seleccionables. Tamaño de caracteres 8. +class GuardarViaje: public Menu{ + public: + virtual void button5pressed(DogMLCD* lcd); +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pantallas/NuevoViaje.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,360 @@ +#include "NuevoViaje.h" +/// ACELEROMETRO DIGITAL/// +KXR94 kionix(p11,p12,p13,p21); + +extern ScreenManager SC; +extern SistemaArchivos SA; +extern Configuracion config; +extern MSCFileSystem msc; +extern FechaHora FH; + +extern DigitalOut myled; +extern DigitalIn boton5; +extern DigitalIn boton6; + +extern Timer t; // Temporizador usado para controlar la animación de la pantalla + +NuevoViaje::NuevoViaje(char newtitle[], char newsubtitle[], char newmsg11[], char newmsg12[], char newmsg2[]){ + strcpy(title, newtitle); + strcpy(subtitle, newsubtitle); + strcpy(msg11, newmsg11); + strcpy(msg12, newmsg12); + strcpy(msg2, newmsg2); +} + +void NuevoViaje::initialize(DogMLCD* lcd){ + // Inicilización de las variables + aXanterior = 0; + aYanterior = 0; + aZanterior = 0; + + ContadorDatos = 0; + pulsado5 = false; + pulsado6 = false; + leyendoDatos = false; + PasoTiempo = 1.0e6/config.getVelocidadAdquisicion(); + + // select font to use: + lcd->XFont = xfont_11; + + // output title text + lcd->XString( OFFSETX, OFFSETY, title); + + lcd->XFont = xfont_8; + + // output subtitle text + char aux[MAXCAR*2]; + char aux2[MAXCAR]; + strcpy(aux, subtitle); + config.getVelocidadAdquisicionString(aux2); + strcat(aux, aux2); + strcat(aux, " Hz"); + lcd->XString( OFFSETX, OFFSETY + 11, aux); + + // output msg2 text + lcd->XString( OFFSETX, HEIGHT -1 - 8, msg2); + + // Se pinta el recuadro del gráfico animado + lcd->Frame(POSX0, POSY0, POSX0 + WIDTHFRAME, POSY0 + HEIGHTFRAME); + + // Se pinta el recuadro lleno que se moverá dentro dle recuadro pintado anteriormente + lcd->Rect(POSX0 + 1, POSY0 + 1, POSX0 + 1 + WIDTHRECT, POSY0 + HEIGHTFRAME); + + // Se inicializa el sentido de la animación (sentido en el que se mueve incialmente el recuadro + posXF = POSX0 + 1 + WIDTHRECT; + sentidoAnimacion = true; + + // transmit work screen to physical screen: + lcd->Flush(); + + // se actualiza la fecha + FH.update(); + + // El archivo donde se guardarán los datos es la fecha y hora con formato con la extensión .txt + char fileName[64]; + char auxTime[64]; + + strcpy(auxTime, FH.getFechaHora()); + strcpy(fileName, "/usb/RAW"); + strcat(fileName, auxTime); + strcat(fileName, ".txt"); + + // Se prepara el USB para escribir en él + // Si el USB está desconectado se avisa del error + if(msc.disk_initialize()){ + SC.changeScreen("USBdesconectado"); + } + + // Se inicia el contador para comprobar si el USB se ha quedado colgado y se activa el ticker que cumple esta función + //t.start(); + // Cada segundo se comprueba si el USB se ha quedado colgado (o no está conectado) + //USBcolgado.attach(this, &NuevoViaje::compruebaUSB, 1); + + fp = fopen(fileName, "w"); + if(fp == NULL){ // Si el USB está desconectado o lleno se avisa por pantalla y se vuelve al menú + // Se desactiva y reseta el timer + /*t.stop(); + t.reset(); + USBcolgado.detach();*/ + SC.changeScreen("USBdesconectado"); + }else{ // Si no se prepara el acelerómetro para comenzar con las lecturas + // Se cargan los valores de calibración del acelerómetro + ParametrosCalibracion::leerValores(valoresCal); + + /*FILE* fp = fopen("/local/prueba2.txt","w"); + fprintf(fp, "%f\n%f\n%f\n%f\n%f\n%f\n", valoresCal[0], valoresCal[1], valoresCal[2], valoresCal[3], valoresCal[4], valoresCal[5]); + fclose(fp);*/ + + // Se crean los buffer donde se guardarán los datos + buff_aX = new Buffering(); + buff_aY = new Buffering(); + buff_aZ = new Buffering(); + + kionix.AcelerometroWakeUp(); + // Hasta que no está preparado no se muestra el mensaje de "OK para comenzar" + // output msg11 text + // select font to use: + lcd->XFont = xfont_11; + lcd->XString(OFFSETX, HEIGHT -1 - 8 - 11, msg11); // Se pinta más arriba para que haya más espacio + + // transmit work screen to physical screen: + lcd->Flush(); + } + + // Debug + //llamadasTicker = 0; +} + +void NuevoViaje::update(DogMLCD* lcd){ + // ANIMACIÓN + // Si se están leyendo datos + if(leyendoDatos){ + if(t.read_ms() >= UPDATETIME){ + // Se procede de forma distinta según el sentido de movimiento del recuadro + if(sentidoAnimacion){ // Derecha + // Se pinta la siguiente columna del recuadro + lcd->LineV(posXF + 1, POSY0 + 1, POSY0 + HEIGHTFRAME-1); + + // Se borra la correspondiente para que el recuadro siga teniendo el mismo tamaño + lcd->LineV(posXF - WIDTHRECT, POSY0 + 1, POSY0 + HEIGHTFRAME-1, wipe); + posXF++; + + // Si se ha llegado al final del frame, se cambia de sentido y se sitúa la variable posXF en la izquierda del recuadro animado + if(posXF >= POSX0 + WIDTHFRAME - 1){ + sentidoAnimacion = false; + posXF = POSX0 + WIDTHFRAME - WIDTHRECT; + } + }else{ // Izquierda + // Se pinta la siguiente columna del recuadro + lcd->LineV(posXF - 1, POSY0 + 1, POSY0 + HEIGHTFRAME-1); + + // Se borra la correspondiente para que el recuadro siga teniendo el mismo tamaño + lcd->LineV(posXF + WIDTHRECT - 1, POSY0 + 1, POSY0 + HEIGHTFRAME-1, wipe); + posXF--; + + // Si se ha llegado al final del frame, se cambia de sentido y se sitúa la variable posXF en la derecha del recudro animado + if(posXF <= POSX0 + 2){ + sentidoAnimacion = true; + posXF = POSX0 + 1 + WIDTHRECT; + } + } + + // Se envía a la pantalla la actualización(tener cuidado con las páginas que se envían) + lcd->Flush(3, 0, posXF+WIDTHRECT+1); + lcd->Flush(4, 0, posXF+WIDTHRECT+1); + + // Se resetea el contador + t.reset(); + } + } + + if(boton5 == 1){ + pulsado5 = true; + }else{ + if(pulsado5 == true){ // El boton ha sido pulsado + pulsado5 = false; + if(!leyendoDatos){ // Si el viaje no habia comenzado + // Primero hay que comprobar si el USB está desconectado + leyendoDatos = true; + // Se inicia el timer que controlará el temporizador + t.reset(); + t.start(); + + // Debug + /*time.reset(); + time.start();*/ + + // Se comienza a leer el acelerómetro + tickerLectura.attach_us(this, &NuevoViaje::LeeAcelerometroBuffer, PasoTiempo); + // Se cambia el mensaje 11 por el 12 + // para ello se pinta un rectángulo vacío en la posición de los caracteres anteriores y se pinta encima los nuevos caracteres + int y0 = HEIGHT -1 - 8 - 11; + for(int i = 0; i < WIDTH; i++){ + for(int k = y0; k < (y0 + 11); k++){ + lcd->Wipe(i,k); + } + } + + // select font to use: + lcd->XFont = xfont_11; + + // output msg11 text + lcd->XString( OFFSETX, HEIGHT -1 - 8 - 11, msg12); // Se pinta más arriba para que haya más espacio + + // transmit work screen to physical screen: + lcd->Flush(); + }else{ // Si el viaje estaba en curso y se desea finalizar + + // Se duerme el acelerómetro + kionix.AcelerometroSleep(); + tickerLectura.detach(); + + fclose(fp); //cierra fichero con datos en el USB + // Se deja libre la memoria de los buffer + delete buff_aX; + delete buff_aY; + delete buff_aZ; + + // Se para el temporizador + t.stop(); + + // Debug + //time.stop(); + + // Debug + /*FILE* fp = fopen("/local/prueba3.txt","w"); + fprintf(fp, "%d, %d", ContadorDatos, llamadasTicker); + fclose(fp); */ + + // Se pasa a la pantalla de guardado del viaje + SC.changeScreen("archivoGuardado"); + } + } + } + + // Botón atrás + if(boton6 == 1){ + pulsado6 = true; + }else{ + if(pulsado6 == true){ + pulsado6 = false; + // Solo se volverá al menú si el viaje no está en proceso + if(!leyendoDatos){ + fclose(fp); //cierra fichero con datos en el USB + // Se duerme el acelerómetro + kionix.AcelerometroSleep(); + // Se deja libre la memoria de los buffer + delete buff_aX; + delete buff_aY; + delete buff_aZ; + SC.changeScreen("menu"); + } + + } + } + // Siempre que existan datos por guardar, se guardan en el USB + GuardaDatosBuffer(); +} + +void NuevoViaje::LeeAcelerometroBuffer() +{ + // Debug + //llamadasTicker++; + + kionix.ReadAccels_KXR94(readings); + + aaX = (int16_t)readings[0]; + aaY = (int16_t)readings[1]; + aaZ = (int16_t)readings[2]; + + buff_aX->put(aaX); + buff_aY->put(aaY); + buff_aZ->put(aaZ); +} + +void NuevoViaje::GuardaDatosBuffer() +{ + bool empty = buff_aX->isEmpty(); + + int dif; //Diferencia entre writting index y riding index. El buffer se llena cuando esta diferencia alcanza el tamaño del buffer + float tiempo; //Tiempo en segundos + + if(empty == false) + { + aXr = buff_aX->get(); + aYr = buff_aY->get(); + aZr = buff_aZ->get(); + + // Debug + // Usar las líneas de código inferiores para depurar el buffering + /*int wi = buff_aX->getWritingIndex(); + int ri = buff_aX->getReadingIndex(); + int dif = buff_aX->getDif();*/ + + aX = (-1.0)*((float)aXr-(valoresCal[0]))*valoresCal[3]; + aY = (-1.0)*((float)aYr-(valoresCal[1]))*valoresCal[4]; + aZ = (-1.0)*((float)aZr-(valoresCal[2]))*valoresCal[5]; + // Para evitar algunos fallos por saturación todo valor mayor que 20 se le da el valor del punto anterior + if(aX > 20.0){ + aX = aXanterior; + } + if(aY > 20.0){ + aY = aYanterior; + } + if(aZ > 20.0){ + aZ = aZanterior; + } + + // También se debe calcular la saturación en 0, por ello si un valor es menor (en valor absoluto) + // que la precisión del acelerómetro se le da también el valor del punto anterior + if(aX*1000 == 0.0000 ){ + aX = aXanterior; + } + if(aY*1000 == 0.0000){ + aY = aYanterior; + } + if(aZ*1000 == 0.0000){ + aZ = aZanterior; + } + + aXanterior = aX; + aYanterior = aY; + aZanterior = aZ; + + + tiempo = ((float)ContadorDatos)*((float)PasoTiempo)/1.0e6; + ContadorDatos++; + + //if(fprintf(fp,"%f %f %f %f\n", tiempo, aXr, aYr, aZr) < 0){ // Pruebas + if(fprintf(fp,"%f %f %f %f\n", tiempo, aX, aY, aZ) < 0){ + //if(fprintf(fp,"%f\n", tiempo) < 0){ // Pruebas + //if(fprintf(fp,"%f %f %f %f %d %d %d\n", tiempo, aX, aY, aZ, wi, ri, dif) < 0){ // pruebas + //if(fprintf(fp,"%d %f %f %f %d %d %d\n", time.read_us(), aX, aY, aZ, wi, ri, dif) < 0){ // pruebas + //if(fprintf(fp,"%f %f %f %f %d %d %d\n", tiempo, aX, aY, aZ, llamadasTicker, ContadorDatos, llamadasTicker-ContadorDatos) < 0){ // pruebas + // Si se sigue estando en la pantalla de NuevoViaje se aborta la lectura de datos y se muestra por pantalla que el USB ha sido desconectado + if(strcmp(SC.getCurrentScreen(), "viaje") == 0){ + + // Se duerme el acelerómetro + kionix.AcelerometroSleep(); + tickerLectura.detach(); + fclose(fp); //cierra fichero con datos en el USB + // Se deja libre la memoria de los buffer + delete buff_aX; + delete buff_aY; + delete buff_aZ; + myled = 1; + SC.changeScreen("USBdesconectado"); + } + } + + // Debug + // Código para ralentizar la mbed + /*for(int i = 0; i< 10000000; i++){ + int prueba34 = prueba34*prueba34/17*23425434; + }*/ + } +} + + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pantallas/NuevoViaje.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,82 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + * Pantalla de nuevo viaje. En esta se leeran los datos del acelerómetro y se guardarán en memoria, si es necesario utilizando buffering + * Mientras se elle también se mostrará una pequeña animación para que de la sensación de que el dispositivo está leyendo datos + */ +#ifndef NUEVOVIAJE_H +#define NUEVOVIAJE_H + +#include "mbed.h" +#include "SistemaArchivos.h" +#include "ScreenManager.h" +#include "MSCFileSystem.h" +#include "Configuracion.h" +#include "FechaHora.h" +#include "KXR94.h" +#include "Buffering.h" +#include <stdlib.h> +#include "ParametrosCalibracion.h" + +#define TUSBCOLGADO 2 // tiempo en segundos que se espera a que responda el USB, en caso contrario se considera que se ha quedado colgado + +#define MAXCAR 32 +#define OFFSETX 4 // Espacio en pixeles que se deja antes de escribir una linea de caracteres +#define OFFSETY 2 // Espacio en pixeles que se deja antes de escribir una linea de caracteres en la parte superior +//#define SIZEBUFF 250 // Tamaño del buffer de datos + +#define COUNTPRECISION 0.00958 // Precisión del dispositivo (mínimo valor de cambio teórico, se calcula como: 4*g/2^12) + +// Definiciones gráfico animado +#define POSX0 13 +#define WIDTHFRAME 100 +#define POSY0 23 +#define HEIGHTFRAME 17 + +#define WIDTHRECT 10 // Ancho del recuadro interior que se mueve a medida que se gravan los datos, el alto del recuadro es el máximo que cabe dentro del frame (8 pixeles, el alto de una página) +#define UPDATETIME 15 // Tiempo en ms que tarda en avanzar una columna el recuadro del gráfico animado + +class NuevoViaje : public Screen { + public: + NuevoViaje(char newtitle[], char newsubtitle[], char newmsg11[], char newmsg12[], char newmsg2[]); + virtual void initialize(DogMLCD* lcd); + virtual void update(DogMLCD* lcd); + + private: + char title[MAXCAR]; + char subtitle[MAXCAR]; + char msg11[MAXCAR]; + char msg12[MAXCAR]; + char msg2[MAXCAR]; + bool pulsado5; + bool pulsado6; + bool leyendoDatos; // Indica si el viaje está o no en proceso + unsigned int PasoTiempo; // Guarda el tiempo en microsegundos que debe de pasar entre cada lectura + + Buffering *buff_aX; + Buffering *buff_aZ; + Buffering *buff_aY; + + FILE * fp; // Puntero al fichero donde se escribirán los datos + + float valoresCal[6]; // Valores de calibración del acelerómetro + int readings[3]; //Lectura aceleraciones sensor digital + float aX, aY, aZ; //Medidas de aceleracion + float aXanterior, aYanterior, aZanterior; //Medidas de aceleracion del punto anterior + int16_t aaX, aaY, aaZ; //Medidas de aceleracion y tiempo + + float aXr, aYr, aZr; // Tiempo y medidas de aceleracion leidos del buffer + unsigned int ContadorDatos; + + Ticker tickerLectura; + void LeeAcelerometroBuffer(); + void GuardaDatosBuffer(); + + bool sentidoAnimacion; // Sentido del movimiento del recuadro de la animación (true: derecha, false: izquierda) + char posXF; // Guarda la posición de la última columna del recuadro de la animación que ha sido pintado + + // Debug + /*unsigned int llamadasTicker; + Timer time;*/ +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pantallas/OpcionesViaje.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,47 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#include "OpcionesViaje.h" + +extern ScreenManager SC; +extern SistemaArchivos SA; +extern Teclado keyboard; +extern GuardarOtroNombre guardadoCorrect; +extern GuardarOtroNombre guardadoCorrectEN; + +extern DigitalOut myled; + +void OpcionesViaje::button5pressed(DogMLCD* lcd){ + bool llamarRaiz = true; // Se usa para llamar o no a la función padre (para controlar los cambios de pantalla) + // Se cambia el idioma actual y se guarda tambien en el fichero de configuracion + switch(getSelect()){ + // Cambiar nombre + case 0: + guardadoCorrect.setNextScreen("listadoViajes"); + guardadoCorrectEN.setNextScreen("listadoViajes"); + guardadoCorrect.setBackScreen("listadoViajes"); + guardadoCorrectEN.setBackScreen("listadoViajes"); + guardadoCorrect.setNombreAntiguo(nombreViaje); + guardadoCorrectEN.setNombreAntiguo(nombreViaje); + keyboard.setBackScreen("rOptions"); + keyboard.setNextScreen("fileSaved"); + break; + // Borrar viaje + case 1: + llamarRaiz = false; + + if(SA.deleteRide(nombreViaje)){ // Si no se pudo borrar se avisa por pantalla de USB + SC.changeScreen("USBdesconectado"); + }else{ + SC.changeScreen("archivoBorrado"); + } + break; + } + if(llamarRaiz){ + Menu::button5pressed(lcd); + } +} + +void OpcionesViaje::setViaje(char *nombre){ + nombreViaje = nombre; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pantallas/OpcionesViaje.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,27 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#ifndef OPCIONESVIAJE_H +#define OPCIONESVIAJE_H + +#include "Menu.h" +#include "SistemaArchivos.h" +#include "MSCFileSystem.h" +#include "ScreenManager.h" +#include "FechaHora.h" +#include "Teclado.h" +#include "GuardarOtroNombre.h" + +// Lista de elementos seleccionables. Tamaño de caracteres 8. +class OpcionesViaje: public Menu{ + public: + virtual void button5pressed(DogMLCD* lcd); + + void setViaje(char *nombre); // Configura el viaje sobre el que actuará este menú + + private: + + char *nombreViaje; +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pantallas/Portada.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,855 @@ +#include "mbed.h" +#include "ScreenManager.h" + +#define ANCHO 128 +#define ALTO 26 +#define XPOS 0 +#define YPOS 11 + +extern ScreenManager SC; + +class Portada : public Screen { + + public: + virtual void initialize(DogMLCD* lcd){ + + lcd->Clear(); + + + lcd->Poke(XPOS + 122, YPOS); + + lcd->Poke(XPOS + 121, YPOS + 1); + lcd->Poke(XPOS + 122, YPOS + 1); + lcd->Poke(XPOS + 123, YPOS + 1); + + lcd->Poke(XPOS + 121, YPOS + 2); + lcd->Poke(XPOS + 122, YPOS + 2); + lcd->Poke(XPOS + 123, YPOS + 2); + + lcd->Poke(XPOS + 121, YPOS + 3); + lcd->Poke(XPOS + 122, YPOS + 3); + lcd->Poke(XPOS + 123, YPOS + 3); + + lcd->Poke(XPOS + 121, YPOS + 4); + lcd->Poke(XPOS + 122, YPOS + 4); + lcd->Poke(XPOS + 123, YPOS + 4); + + lcd->Poke(XPOS + 120, YPOS + 5); + lcd->Poke(XPOS + 121, YPOS + 5); + lcd->Poke(XPOS + 122, YPOS + 5); + lcd->Poke(XPOS + 123, YPOS + 5); + lcd->Poke(XPOS + 124, YPOS + 5); + + lcd->Poke(XPOS + 117, YPOS + 6); + lcd->Poke(XPOS + 118, YPOS + 6); + lcd->Poke(XPOS + 119, YPOS + 6); + lcd->Poke(XPOS + 120, YPOS + 6); + lcd->Poke(XPOS + 121, YPOS + 6); + lcd->Poke(XPOS + 122, YPOS + 6); + lcd->Poke(XPOS + 123, YPOS + 6); + lcd->Poke(XPOS + 124, YPOS + 6); + lcd->Poke(XPOS + 125, YPOS + 6); + + lcd->Poke(XPOS + 116, YPOS + 7); + lcd->Poke(XPOS + 117, YPOS + 7); + lcd->Poke(XPOS + 118, YPOS + 7); + lcd->Poke(XPOS + 119, YPOS + 7); + lcd->Poke(XPOS + 120, YPOS + 7); + lcd->Poke(XPOS + 121, YPOS + 7); + lcd->Poke(XPOS + 122, YPOS + 7); + lcd->Poke(XPOS + 123, YPOS + 7); + lcd->Poke(XPOS + 124, YPOS + 7); + lcd->Poke(XPOS + 125, YPOS + 7); + lcd->Poke(XPOS + 126, YPOS + 7); + + lcd->Poke(XPOS + 13, YPOS + 8); + lcd->Poke(XPOS + 14, YPOS + 8); + lcd->Poke(XPOS + 110, YPOS + 8); + lcd->Poke(XPOS + 111, YPOS + 8); + lcd->Poke(XPOS + 116, YPOS + 8); + lcd->Poke(XPOS + 117, YPOS + 8); + lcd->Poke(XPOS + 118, YPOS + 8); + lcd->Poke(XPOS + 119, YPOS + 8); + lcd->Poke(XPOS + 120, YPOS + 8); + lcd->Poke(XPOS + 121, YPOS + 8); + lcd->Poke(XPOS + 123, YPOS + 8); + lcd->Poke(XPOS + 124, YPOS + 8); + lcd->Poke(XPOS + 125, YPOS + 8); + lcd->Poke(XPOS + 126, YPOS + 8); + lcd->Poke(XPOS + 127, YPOS + 8); + + lcd->Poke(XPOS + 12, YPOS + 9); + lcd->Poke(XPOS + 13, YPOS + 9); + lcd->Poke(XPOS + 14, YPOS + 9); + lcd->Poke(XPOS + 15, YPOS + 9); + lcd->Poke(XPOS + 29, YPOS + 9); + lcd->Poke(XPOS + 61, YPOS + 9); + lcd->Poke(XPOS + 62, YPOS + 9); + lcd->Poke(XPOS + 109, YPOS + 9); + lcd->Poke(XPOS + 110, YPOS + 9); + lcd->Poke(XPOS + 111, YPOS + 9); + lcd->Poke(XPOS + 117, YPOS + 9); + lcd->Poke(XPOS + 118, YPOS + 9); + lcd->Poke(XPOS + 119, YPOS + 9); + lcd->Poke(XPOS + 124, YPOS + 9); + lcd->Poke(XPOS + 125, YPOS + 9); + lcd->Poke(XPOS + 126, YPOS + 9); + lcd->Poke(XPOS + 127, YPOS + 9); + + lcd->Poke(XPOS + 12, YPOS + 10); + lcd->Poke(XPOS + 13, YPOS + 10); + lcd->Poke(XPOS + 14, YPOS + 10); + lcd->Poke(XPOS + 15, YPOS + 10); + lcd->Poke(XPOS + 28, YPOS + 10); + lcd->Poke(XPOS + 29, YPOS + 10); + lcd->Poke(XPOS + 61, YPOS + 10); + lcd->Poke(XPOS + 62, YPOS + 10); + lcd->Poke(XPOS + 109, YPOS + 10); + lcd->Poke(XPOS + 110, YPOS + 10); + lcd->Poke(XPOS + 111, YPOS + 10); + lcd->Poke(XPOS + 125, YPOS + 10); + lcd->Poke(XPOS + 126, YPOS + 10); + lcd->Poke(XPOS + 127, YPOS + 10); + + lcd->Poke(XPOS + 13, YPOS + 11); + lcd->Poke(XPOS + 14, YPOS + 11); + lcd->Poke(XPOS + 28, YPOS + 11); + lcd->Poke(XPOS + 29, YPOS + 11); + lcd->Poke(XPOS + 61, YPOS + 11); + lcd->Poke(XPOS + 62, YPOS + 11); + lcd->Poke(XPOS + 109, YPOS + 11); + lcd->Poke(XPOS + 110, YPOS + 11); + lcd->Poke(XPOS + 111, YPOS + 11); + + lcd->Poke(XPOS + 28, YPOS + 12); + lcd->Poke(XPOS + 29, YPOS + 12); + lcd->Poke(XPOS + 61, YPOS + 12); + lcd->Poke(XPOS + 62, YPOS + 12); + lcd->Poke(XPOS + 109, YPOS + 12); + lcd->Poke(XPOS + 110, YPOS + 12); + lcd->Poke(XPOS + 111, YPOS + 12); + + lcd->Poke(XPOS + 1, YPOS + 13); + lcd->Poke(XPOS + 9, YPOS + 13); + lcd->Poke(XPOS + 13, YPOS + 13); + lcd->Poke(XPOS + 14, YPOS + 13); + lcd->Poke(XPOS + 17, YPOS + 13); + lcd->Poke(XPOS + 18, YPOS + 13); + lcd->Poke(XPOS + 21, YPOS + 13); + lcd->Poke(XPOS + 22, YPOS + 13); + lcd->Poke(XPOS + 23, YPOS + 13); + lcd->Poke(XPOS + 27, YPOS + 13); + lcd->Poke(XPOS + 28, YPOS + 13); + lcd->Poke(XPOS + 29, YPOS + 13); + lcd->Poke(XPOS + 30, YPOS + 13); + lcd->Poke(XPOS + 37, YPOS + 13); + lcd->Poke(XPOS + 50, YPOS + 13); + lcd->Poke(XPOS + 51, YPOS + 13); + lcd->Poke(XPOS + 52, YPOS + 13); + lcd->Poke(XPOS + 53, YPOS + 13); + lcd->Poke(XPOS + 54, YPOS + 13); + lcd->Poke(XPOS + 55, YPOS + 13); + lcd->Poke(XPOS + 56, YPOS + 13); + lcd->Poke(XPOS + 61, YPOS + 13); + lcd->Poke(XPOS + 62, YPOS + 13); + lcd->Poke(XPOS + 66, YPOS + 13); + lcd->Poke(XPOS + 70, YPOS + 13); + lcd->Poke(XPOS + 71, YPOS + 13); + lcd->Poke(XPOS + 72, YPOS + 13); + lcd->Poke(XPOS + 77, YPOS + 13); + lcd->Poke(XPOS + 78, YPOS + 13); + lcd->Poke(XPOS + 79, YPOS + 13); + lcd->Poke(XPOS + 87, YPOS + 13); + lcd->Poke(XPOS + 88, YPOS + 13); + lcd->Poke(XPOS + 90, YPOS + 13); + lcd->Poke(XPOS + 91, YPOS + 13); + lcd->Poke(XPOS + 100, YPOS + 13); + lcd->Poke(XPOS + 101, YPOS + 13); + lcd->Poke(XPOS + 102, YPOS + 13); + lcd->Poke(XPOS + 103, YPOS + 13); + lcd->Poke(XPOS + 109, YPOS + 13); + lcd->Poke(XPOS + 110, YPOS + 13); + lcd->Poke(XPOS + 111, YPOS + 13); + lcd->Poke(XPOS + 114, YPOS + 13); + lcd->Poke(XPOS + 115, YPOS + 13); + lcd->Poke(XPOS + 116, YPOS + 13); + lcd->Poke(XPOS + 117, YPOS + 13); + + lcd->Poke(XPOS + 0, YPOS + 14); + lcd->Poke(XPOS + 1, YPOS + 14); + lcd->Poke(XPOS + 2, YPOS + 14); + lcd->Poke(XPOS + 8, YPOS + 14); + lcd->Poke(XPOS + 9, YPOS + 14); + lcd->Poke(XPOS + 10, YPOS + 14); + lcd->Poke(XPOS + 13, YPOS + 14); + lcd->Poke(XPOS + 14, YPOS + 14); + lcd->Poke(XPOS + 17, YPOS + 14); + lcd->Poke(XPOS + 18, YPOS + 14); + lcd->Poke(XPOS + 19, YPOS + 14); + lcd->Poke(XPOS + 20, YPOS + 14); + lcd->Poke(XPOS + 21, YPOS + 14); + lcd->Poke(XPOS + 22, YPOS + 14); + lcd->Poke(XPOS + 23, YPOS + 14); + lcd->Poke(XPOS + 24, YPOS + 14); + lcd->Poke(XPOS + 26, YPOS + 14); + lcd->Poke(XPOS + 27, YPOS + 14); + lcd->Poke(XPOS + 28, YPOS + 14); + lcd->Poke(XPOS + 29, YPOS + 14); + lcd->Poke(XPOS + 30, YPOS + 14); + lcd->Poke(XPOS + 31, YPOS + 14); + lcd->Poke(XPOS + 32, YPOS + 14); + lcd->Poke(XPOS + 36, YPOS + 14); + lcd->Poke(XPOS + 37, YPOS + 14); + lcd->Poke(XPOS + 38, YPOS + 14); + lcd->Poke(XPOS + 44, YPOS + 14); + lcd->Poke(XPOS + 45, YPOS + 14); + lcd->Poke(XPOS + 49, YPOS + 14); + lcd->Poke(XPOS + 50, YPOS + 14); + lcd->Poke(XPOS + 51, YPOS + 14); + lcd->Poke(XPOS + 52, YPOS + 14); + lcd->Poke(XPOS + 53, YPOS + 14); + lcd->Poke(XPOS + 54, YPOS + 14); + lcd->Poke(XPOS + 55, YPOS + 14); + lcd->Poke(XPOS + 56, YPOS + 14); + lcd->Poke(XPOS + 57, YPOS + 14); + lcd->Poke(XPOS + 61, YPOS + 14); + lcd->Poke(XPOS + 62, YPOS + 14); + lcd->Poke(XPOS + 65, YPOS + 14); + lcd->Poke(XPOS + 66, YPOS + 14); + lcd->Poke(XPOS + 67, YPOS + 14); + lcd->Poke(XPOS + 69, YPOS + 14); + lcd->Poke(XPOS + 70, YPOS + 14); + lcd->Poke(XPOS + 71, YPOS + 14); + lcd->Poke(XPOS + 72, YPOS + 14); + lcd->Poke(XPOS + 73, YPOS + 14); + lcd->Poke(XPOS + 76, YPOS + 14); + lcd->Poke(XPOS + 77, YPOS + 14); + lcd->Poke(XPOS + 78, YPOS + 14); + lcd->Poke(XPOS + 79, YPOS + 14); + lcd->Poke(XPOS + 80, YPOS + 14); + lcd->Poke(XPOS + 86, YPOS + 14); + lcd->Poke(XPOS + 87, YPOS + 14); + lcd->Poke(XPOS + 88, YPOS + 14); + lcd->Poke(XPOS + 90, YPOS + 14); + lcd->Poke(XPOS + 91, YPOS + 14); + lcd->Poke(XPOS + 92, YPOS + 14); + lcd->Poke(XPOS + 99, YPOS + 14); + lcd->Poke(XPOS + 100, YPOS + 14); + lcd->Poke(XPOS + 101, YPOS + 14); + lcd->Poke(XPOS + 102, YPOS + 14); + lcd->Poke(XPOS + 103, YPOS + 14); + lcd->Poke(XPOS + 104, YPOS + 14); + lcd->Poke(XPOS + 105, YPOS + 14); + lcd->Poke(XPOS + 109, YPOS + 14); + lcd->Poke(XPOS + 110, YPOS + 14); + lcd->Poke(XPOS + 111, YPOS + 14); + lcd->Poke(XPOS + 113, YPOS + 14); + lcd->Poke(XPOS + 114, YPOS + 14); + lcd->Poke(XPOS + 115, YPOS + 14); + lcd->Poke(XPOS + 116, YPOS + 14); + lcd->Poke(XPOS + 117, YPOS + 14); + lcd->Poke(XPOS + 118, YPOS + 14); + + lcd->Poke(XPOS + 0, YPOS + 15); + lcd->Poke(XPOS + 1, YPOS + 15); + lcd->Poke(XPOS + 2, YPOS + 15); + lcd->Poke(XPOS + 8, YPOS + 15); + lcd->Poke(XPOS + 9, YPOS + 15); + lcd->Poke(XPOS + 10, YPOS + 15); + lcd->Poke(XPOS + 13, YPOS + 15); + lcd->Poke(XPOS + 14, YPOS + 15); + lcd->Poke(XPOS + 17, YPOS + 15); + lcd->Poke(XPOS + 18, YPOS + 15); + lcd->Poke(XPOS + 19, YPOS + 15); + lcd->Poke(XPOS + 20, YPOS + 15); + lcd->Poke(XPOS + 21, YPOS + 15); + lcd->Poke(XPOS + 22, YPOS + 15); + lcd->Poke(XPOS + 23, YPOS + 15); + lcd->Poke(XPOS + 24, YPOS + 15); + lcd->Poke(XPOS + 27, YPOS + 15); + lcd->Poke(XPOS + 28, YPOS + 15); + lcd->Poke(XPOS + 29, YPOS + 15); + lcd->Poke(XPOS + 30, YPOS + 15); + lcd->Poke(XPOS + 36, YPOS + 15); + lcd->Poke(XPOS + 37, YPOS + 15); + lcd->Poke(XPOS + 38, YPOS + 15); + lcd->Poke(XPOS + 44, YPOS + 15); + lcd->Poke(XPOS + 45, YPOS + 15); + lcd->Poke(XPOS + 48, YPOS + 15); + lcd->Poke(XPOS + 49, YPOS + 15); + lcd->Poke(XPOS + 50, YPOS + 15); + lcd->Poke(XPOS + 51, YPOS + 15); + lcd->Poke(XPOS + 52, YPOS + 15); + lcd->Poke(XPOS + 54, YPOS + 15); + lcd->Poke(XPOS + 55, YPOS + 15); + lcd->Poke(XPOS + 56, YPOS + 15); + lcd->Poke(XPOS + 57, YPOS + 15); + lcd->Poke(XPOS + 58, YPOS + 15); + lcd->Poke(XPOS + 61, YPOS + 15); + lcd->Poke(XPOS + 62, YPOS + 15); + lcd->Poke(XPOS + 65, YPOS + 15); + lcd->Poke(XPOS + 66, YPOS + 15); + lcd->Poke(XPOS + 67, YPOS + 15); + lcd->Poke(XPOS + 68, YPOS + 15); + lcd->Poke(XPOS + 69, YPOS + 15); + lcd->Poke(XPOS + 70, YPOS + 15); + lcd->Poke(XPOS + 71, YPOS + 15); + lcd->Poke(XPOS + 72, YPOS + 15); + lcd->Poke(XPOS + 73, YPOS + 15); + lcd->Poke(XPOS + 74, YPOS + 15); + lcd->Poke(XPOS + 75, YPOS + 15); + lcd->Poke(XPOS + 76, YPOS + 15); + lcd->Poke(XPOS + 77, YPOS + 15); + lcd->Poke(XPOS + 78, YPOS + 15); + lcd->Poke(XPOS + 79, YPOS + 15); + lcd->Poke(XPOS + 80, YPOS + 15); + lcd->Poke(XPOS + 81, YPOS + 15); + lcd->Poke(XPOS + 85, YPOS + 15); + lcd->Poke(XPOS + 86, YPOS + 15); + lcd->Poke(XPOS + 87, YPOS + 15); + lcd->Poke(XPOS + 88, YPOS + 15); + lcd->Poke(XPOS + 90, YPOS + 15); + lcd->Poke(XPOS + 91, YPOS + 15); + lcd->Poke(XPOS + 92, YPOS + 15); + lcd->Poke(XPOS + 93, YPOS + 15); + lcd->Poke(XPOS + 98, YPOS + 15); + lcd->Poke(XPOS + 99, YPOS + 15); + lcd->Poke(XPOS + 100, YPOS + 15); + lcd->Poke(XPOS + 104, YPOS + 15); + lcd->Poke(XPOS + 105, YPOS + 15); + lcd->Poke(XPOS + 106, YPOS + 15); + lcd->Poke(XPOS + 109, YPOS + 15); + lcd->Poke(XPOS + 110, YPOS + 15); + lcd->Poke(XPOS + 111, YPOS + 15); + lcd->Poke(XPOS + 112, YPOS + 15); + lcd->Poke(XPOS + 113, YPOS + 15); + lcd->Poke(XPOS + 114, YPOS + 15); + lcd->Poke(XPOS + 115, YPOS + 15); + lcd->Poke(XPOS + 116, YPOS + 15); + lcd->Poke(XPOS + 117, YPOS + 15); + lcd->Poke(XPOS + 118, YPOS + 15); + lcd->Poke(XPOS + 119, YPOS + 15); + + lcd->Poke(XPOS + 1, YPOS + 16); + lcd->Poke(XPOS + 2, YPOS + 16); + lcd->Poke(XPOS + 8, YPOS + 16); + lcd->Poke(XPOS + 9, YPOS + 16); + lcd->Poke(XPOS + 13, YPOS + 16); + lcd->Poke(XPOS + 14, YPOS + 16); + lcd->Poke(XPOS + 17, YPOS + 16); + lcd->Poke(XPOS + 18, YPOS + 16); + lcd->Poke(XPOS + 19, YPOS + 16); + lcd->Poke(XPOS + 20, YPOS + 16); + lcd->Poke(XPOS + 23, YPOS + 16); + lcd->Poke(XPOS + 28, YPOS + 16); + lcd->Poke(XPOS + 29, YPOS + 16); + lcd->Poke(XPOS + 36, YPOS + 16); + lcd->Poke(XPOS + 37, YPOS + 16); + lcd->Poke(XPOS + 38, YPOS + 16); + lcd->Poke(XPOS + 44, YPOS + 16); + lcd->Poke(XPOS + 45, YPOS + 16); + lcd->Poke(XPOS + 48, YPOS + 16); + lcd->Poke(XPOS + 49, YPOS + 16); + lcd->Poke(XPOS + 50, YPOS + 16); + lcd->Poke(XPOS + 55, YPOS + 16); + lcd->Poke(XPOS + 56, YPOS + 16); + lcd->Poke(XPOS + 57, YPOS + 16); + lcd->Poke(XPOS + 58, YPOS + 16); + lcd->Poke(XPOS + 61, YPOS + 16); + lcd->Poke(XPOS + 62, YPOS + 16); + lcd->Poke(XPOS + 65, YPOS + 16); + lcd->Poke(XPOS + 66, YPOS + 16); + lcd->Poke(XPOS + 67, YPOS + 16); + lcd->Poke(XPOS + 68, YPOS + 16); + lcd->Poke(XPOS + 72, YPOS + 16); + lcd->Poke(XPOS + 73, YPOS + 16); + lcd->Poke(XPOS + 74, YPOS + 16); + lcd->Poke(XPOS + 75, YPOS + 16); + lcd->Poke(XPOS + 79, YPOS + 16); + lcd->Poke(XPOS + 80, YPOS + 16); + lcd->Poke(XPOS + 81, YPOS + 16); + lcd->Poke(XPOS + 84, YPOS + 16); + lcd->Poke(XPOS + 85, YPOS + 16); + lcd->Poke(XPOS + 86, YPOS + 16); + lcd->Poke(XPOS + 87, YPOS + 16); + lcd->Poke(XPOS + 91, YPOS + 16); + lcd->Poke(XPOS + 92, YPOS + 16); + lcd->Poke(XPOS + 93, YPOS + 16); + lcd->Poke(XPOS + 97, YPOS + 16); + lcd->Poke(XPOS + 98, YPOS + 16); + lcd->Poke(XPOS + 99, YPOS + 16); + lcd->Poke(XPOS + 105, YPOS + 16); + lcd->Poke(XPOS + 106, YPOS + 16); + lcd->Poke(XPOS + 109, YPOS + 16); + lcd->Poke(XPOS + 110, YPOS + 16); + lcd->Poke(XPOS + 111, YPOS + 16); + lcd->Poke(XPOS + 112, YPOS + 16); + lcd->Poke(XPOS + 113, YPOS + 16); + lcd->Poke(XPOS + 116, YPOS + 16); + lcd->Poke(XPOS + 117, YPOS + 16); + lcd->Poke(XPOS + 118, YPOS + 16); + lcd->Poke(XPOS + 119, YPOS + 16); + + lcd->Poke(XPOS + 1, YPOS + 17); + lcd->Poke(XPOS + 2, YPOS + 17); + lcd->Poke(XPOS + 3, YPOS + 17); + lcd->Poke(XPOS + 7, YPOS + 17); + lcd->Poke(XPOS + 8, YPOS + 17); + lcd->Poke(XPOS + 9, YPOS + 17); + lcd->Poke(XPOS + 13, YPOS + 17); + lcd->Poke(XPOS + 14, YPOS + 17); + lcd->Poke(XPOS + 17, YPOS + 17); + lcd->Poke(XPOS + 18, YPOS + 17); + lcd->Poke(XPOS + 19, YPOS + 17); + lcd->Poke(XPOS + 28, YPOS + 17); + lcd->Poke(XPOS + 29, YPOS + 17); + lcd->Poke(XPOS + 36, YPOS + 17); + lcd->Poke(XPOS + 37, YPOS + 17); + lcd->Poke(XPOS + 38, YPOS + 17); + lcd->Poke(XPOS + 44, YPOS + 17); + lcd->Poke(XPOS + 45, YPOS + 17); + lcd->Poke(XPOS + 49, YPOS + 17); + lcd->Poke(XPOS + 55, YPOS + 17); + lcd->Poke(XPOS + 56, YPOS + 17); + lcd->Poke(XPOS + 57, YPOS + 17); + lcd->Poke(XPOS + 58, YPOS + 17); + lcd->Poke(XPOS + 61, YPOS + 17); + lcd->Poke(XPOS + 62, YPOS + 17); + lcd->Poke(XPOS + 65, YPOS + 17); + lcd->Poke(XPOS + 66, YPOS + 17); + lcd->Poke(XPOS + 67, YPOS + 17); + lcd->Poke(XPOS + 72, YPOS + 17); + lcd->Poke(XPOS + 73, YPOS + 17); + lcd->Poke(XPOS + 74, YPOS + 17); + lcd->Poke(XPOS + 79, YPOS + 17); + lcd->Poke(XPOS + 80, YPOS + 17); + lcd->Poke(XPOS + 81, YPOS + 17); + lcd->Poke(XPOS + 84, YPOS + 17); + lcd->Poke(XPOS + 85, YPOS + 17); + lcd->Poke(XPOS + 86, YPOS + 17); + lcd->Poke(XPOS + 92, YPOS + 17); + lcd->Poke(XPOS + 93, YPOS + 17); + lcd->Poke(XPOS + 94, YPOS + 17); + lcd->Poke(XPOS + 97, YPOS + 17); + lcd->Poke(XPOS + 98, YPOS + 17); + lcd->Poke(XPOS + 105, YPOS + 17); + lcd->Poke(XPOS + 106, YPOS + 17); + lcd->Poke(XPOS + 109, YPOS + 17); + lcd->Poke(XPOS + 110, YPOS + 17); + lcd->Poke(XPOS + 111, YPOS + 17); + lcd->Poke(XPOS + 112, YPOS + 17); + lcd->Poke(XPOS + 117, YPOS + 17); + lcd->Poke(XPOS + 118, YPOS + 17); + lcd->Poke(XPOS + 119, YPOS + 17); + + lcd->Poke(XPOS + 2, YPOS + 18); + lcd->Poke(XPOS + 3, YPOS + 18); + lcd->Poke(XPOS + 7, YPOS + 18); + lcd->Poke(XPOS + 8, YPOS + 18); + lcd->Poke(XPOS + 13, YPOS + 18); + lcd->Poke(XPOS + 14, YPOS + 18); + lcd->Poke(XPOS + 17, YPOS + 18); + lcd->Poke(XPOS + 18, YPOS + 18); + lcd->Poke(XPOS + 19, YPOS + 18); + lcd->Poke(XPOS + 28, YPOS + 18); + lcd->Poke(XPOS + 29, YPOS + 18); + lcd->Poke(XPOS + 36, YPOS + 18); + lcd->Poke(XPOS + 37, YPOS + 18); + lcd->Poke(XPOS + 38, YPOS + 18); + lcd->Poke(XPOS + 44, YPOS + 18); + lcd->Poke(XPOS + 45, YPOS + 18); + lcd->Poke(XPOS + 55, YPOS + 18); + lcd->Poke(XPOS + 56, YPOS + 18); + lcd->Poke(XPOS + 57, YPOS + 18); + lcd->Poke(XPOS + 58, YPOS + 18); + lcd->Poke(XPOS + 61, YPOS + 18); + lcd->Poke(XPOS + 62, YPOS + 18); + lcd->Poke(XPOS + 65, YPOS + 18); + lcd->Poke(XPOS + 66, YPOS + 18); + lcd->Poke(XPOS + 67, YPOS + 18); + lcd->Poke(XPOS + 72, YPOS + 18); + lcd->Poke(XPOS + 73, YPOS + 18); + lcd->Poke(XPOS + 74, YPOS + 18); + lcd->Poke(XPOS + 79, YPOS + 18); + lcd->Poke(XPOS + 80, YPOS + 18); + lcd->Poke(XPOS + 81, YPOS + 18); + lcd->Poke(XPOS + 84, YPOS + 18); + lcd->Poke(XPOS + 85, YPOS + 18); + lcd->Poke(XPOS + 86, YPOS + 18); + lcd->Poke(XPOS + 92, YPOS + 18); + lcd->Poke(XPOS + 93, YPOS + 18); + lcd->Poke(XPOS + 94, YPOS + 18); + lcd->Poke(XPOS + 97, YPOS + 18); + lcd->Poke(XPOS + 98, YPOS + 18); + lcd->Poke(XPOS + 109, YPOS + 18); + lcd->Poke(XPOS + 110, YPOS + 18); + lcd->Poke(XPOS + 111, YPOS + 18); + lcd->Poke(XPOS + 117, YPOS + 18); + lcd->Poke(XPOS + 118, YPOS + 18); + lcd->Poke(XPOS + 119, YPOS + 18); + + lcd->Poke(XPOS + 2, YPOS + 19); + lcd->Poke(XPOS + 3, YPOS + 19); + lcd->Poke(XPOS + 7, YPOS + 19); + lcd->Poke(XPOS + 8, YPOS + 19); + lcd->Poke(XPOS + 13, YPOS + 19); + lcd->Poke(XPOS + 14, YPOS + 19); + lcd->Poke(XPOS + 17, YPOS + 19); + lcd->Poke(XPOS + 18, YPOS + 19); + lcd->Poke(XPOS + 19, YPOS + 19); + lcd->Poke(XPOS + 28, YPOS + 19); + lcd->Poke(XPOS + 29, YPOS + 19); + lcd->Poke(XPOS + 36, YPOS + 19); + lcd->Poke(XPOS + 37, YPOS + 19); + lcd->Poke(XPOS + 38, YPOS + 19); + lcd->Poke(XPOS + 44, YPOS + 19); + lcd->Poke(XPOS + 45, YPOS + 19); + lcd->Poke(XPOS + 50, YPOS + 19); + lcd->Poke(XPOS + 51, YPOS + 19); + lcd->Poke(XPOS + 54, YPOS + 19); + lcd->Poke(XPOS + 55, YPOS + 19); + lcd->Poke(XPOS + 56, YPOS + 19); + lcd->Poke(XPOS + 57, YPOS + 19); + lcd->Poke(XPOS + 58, YPOS + 19); + lcd->Poke(XPOS + 61, YPOS + 19); + lcd->Poke(XPOS + 62, YPOS + 19); + lcd->Poke(XPOS + 65, YPOS + 19); + lcd->Poke(XPOS + 66, YPOS + 19); + lcd->Poke(XPOS + 67, YPOS + 19); + lcd->Poke(XPOS + 72, YPOS + 19); + lcd->Poke(XPOS + 73, YPOS + 19); + lcd->Poke(XPOS + 74, YPOS + 19); + lcd->Poke(XPOS + 79, YPOS + 19); + lcd->Poke(XPOS + 80, YPOS + 19); + lcd->Poke(XPOS + 81, YPOS + 19); + lcd->Poke(XPOS + 84, YPOS + 19); + lcd->Poke(XPOS + 85, YPOS + 19); + lcd->Poke(XPOS + 86, YPOS + 19); + lcd->Poke(XPOS + 87, YPOS + 19); + lcd->Poke(XPOS + 88, YPOS + 19); + lcd->Poke(XPOS + 90, YPOS + 19); + lcd->Poke(XPOS + 91, YPOS + 19); + lcd->Poke(XPOS + 92, YPOS + 19); + lcd->Poke(XPOS + 93, YPOS + 19); + lcd->Poke(XPOS + 97, YPOS + 19); + lcd->Poke(XPOS + 98, YPOS + 19); + lcd->Poke(XPOS + 109, YPOS + 19); + lcd->Poke(XPOS + 110, YPOS + 19); + lcd->Poke(XPOS + 111, YPOS + 19); + lcd->Poke(XPOS + 117, YPOS + 19); + lcd->Poke(XPOS + 118, YPOS + 19); + lcd->Poke(XPOS + 119, YPOS + 19); + + lcd->Poke(XPOS + 2, YPOS + 20); + lcd->Poke(XPOS + 3, YPOS + 20); + lcd->Poke(XPOS + 7, YPOS + 20); + lcd->Poke(XPOS + 8, YPOS + 20); + lcd->Poke(XPOS + 13, YPOS + 20); + lcd->Poke(XPOS + 14, YPOS + 20); + lcd->Poke(XPOS + 17, YPOS + 20); + lcd->Poke(XPOS + 18, YPOS + 20); + lcd->Poke(XPOS + 19, YPOS + 20); + lcd->Poke(XPOS + 28, YPOS + 20); + lcd->Poke(XPOS + 29, YPOS + 20); + lcd->Poke(XPOS + 36, YPOS + 20); + lcd->Poke(XPOS + 37, YPOS + 20); + lcd->Poke(XPOS + 38, YPOS + 20); + lcd->Poke(XPOS + 44, YPOS + 20); + lcd->Poke(XPOS + 45, YPOS + 20); + lcd->Poke(XPOS + 49, YPOS + 20); + lcd->Poke(XPOS + 50, YPOS + 20); + lcd->Poke(XPOS + 51, YPOS + 20); + lcd->Poke(XPOS + 56, YPOS + 20); + lcd->Poke(XPOS + 57, YPOS + 20); + lcd->Poke(XPOS + 58, YPOS + 20); + lcd->Poke(XPOS + 61, YPOS + 20); + lcd->Poke(XPOS + 62, YPOS + 20); + lcd->Poke(XPOS + 65, YPOS + 20); + lcd->Poke(XPOS + 66, YPOS + 20); + lcd->Poke(XPOS + 67, YPOS + 20); + lcd->Poke(XPOS + 72, YPOS + 20); + lcd->Poke(XPOS + 73, YPOS + 20); + lcd->Poke(XPOS + 74, YPOS + 20); + lcd->Poke(XPOS + 79, YPOS + 20); + lcd->Poke(XPOS + 80, YPOS + 20); + lcd->Poke(XPOS + 81, YPOS + 20); + lcd->Poke(XPOS + 84, YPOS + 20); + lcd->Poke(XPOS + 85, YPOS + 20); + lcd->Poke(XPOS + 86, YPOS + 20); + lcd->Poke(XPOS + 97, YPOS + 20); + lcd->Poke(XPOS + 98, YPOS + 20); + lcd->Poke(XPOS + 109, YPOS + 20); + lcd->Poke(XPOS + 110, YPOS + 20); + lcd->Poke(XPOS + 111, YPOS + 20); + lcd->Poke(XPOS + 117, YPOS + 20); + lcd->Poke(XPOS + 118, YPOS + 20); + lcd->Poke(XPOS + 119, YPOS + 20); + + lcd->Poke(XPOS + 3, YPOS + 21); + lcd->Poke(XPOS + 4, YPOS + 21); + lcd->Poke(XPOS + 6, YPOS + 21); + lcd->Poke(XPOS + 7, YPOS + 21); + lcd->Poke(XPOS + 13, YPOS + 21); + lcd->Poke(XPOS + 14, YPOS + 21); + lcd->Poke(XPOS + 17, YPOS + 21); + lcd->Poke(XPOS + 18, YPOS + 21); + lcd->Poke(XPOS + 19, YPOS + 21); + lcd->Poke(XPOS + 28, YPOS + 21); + lcd->Poke(XPOS + 29, YPOS + 21); + lcd->Poke(XPOS + 36, YPOS + 21); + lcd->Poke(XPOS + 37, YPOS + 21); + lcd->Poke(XPOS + 38, YPOS + 21); + lcd->Poke(XPOS + 44, YPOS + 21); + lcd->Poke(XPOS + 45, YPOS + 21); + lcd->Poke(XPOS + 48, YPOS + 21); + lcd->Poke(XPOS + 49, YPOS + 21); + lcd->Poke(XPOS + 50, YPOS + 21); + lcd->Poke(XPOS + 56, YPOS + 21); + lcd->Poke(XPOS + 57, YPOS + 21); + lcd->Poke(XPOS + 58, YPOS + 21); + lcd->Poke(XPOS + 61, YPOS + 21); + lcd->Poke(XPOS + 62, YPOS + 21); + lcd->Poke(XPOS + 65, YPOS + 21); + lcd->Poke(XPOS + 66, YPOS + 21); + lcd->Poke(XPOS + 67, YPOS + 21); + lcd->Poke(XPOS + 72, YPOS + 21); + lcd->Poke(XPOS + 73, YPOS + 21); + lcd->Poke(XPOS + 74, YPOS + 21); + lcd->Poke(XPOS + 79, YPOS + 21); + lcd->Poke(XPOS + 80, YPOS + 21); + lcd->Poke(XPOS + 81, YPOS + 21); + lcd->Poke(XPOS + 84, YPOS + 21); + lcd->Poke(XPOS + 85, YPOS + 21); + lcd->Poke(XPOS + 86, YPOS + 21); + lcd->Poke(XPOS + 97, YPOS + 21); + lcd->Poke(XPOS + 98, YPOS + 21); + lcd->Poke(XPOS + 99, YPOS + 21); + lcd->Poke(XPOS + 106, YPOS + 21); + lcd->Poke(XPOS + 109, YPOS + 21); + lcd->Poke(XPOS + 110, YPOS + 21); + lcd->Poke(XPOS + 111, YPOS + 21); + lcd->Poke(XPOS + 117, YPOS + 21); + lcd->Poke(XPOS + 118, YPOS + 21); + lcd->Poke(XPOS + 119, YPOS + 21); + + lcd->Poke(XPOS + 3, YPOS + 22); + lcd->Poke(XPOS + 4, YPOS + 22); + lcd->Poke(XPOS + 5, YPOS + 22); + lcd->Poke(XPOS + 6, YPOS + 22); + lcd->Poke(XPOS + 7, YPOS + 22); + lcd->Poke(XPOS + 13, YPOS + 22); + lcd->Poke(XPOS + 14, YPOS + 22); + lcd->Poke(XPOS + 17, YPOS + 22); + lcd->Poke(XPOS + 18, YPOS + 22); + lcd->Poke(XPOS + 19, YPOS + 22); + lcd->Poke(XPOS + 28, YPOS + 22); + lcd->Poke(XPOS + 29, YPOS + 22); + lcd->Poke(XPOS + 36, YPOS + 22); + lcd->Poke(XPOS + 37, YPOS + 22); + lcd->Poke(XPOS + 38, YPOS + 22); + lcd->Poke(XPOS + 43, YPOS + 22); + lcd->Poke(XPOS + 44, YPOS + 22); + lcd->Poke(XPOS + 45, YPOS + 22); + lcd->Poke(XPOS + 48, YPOS + 22); + lcd->Poke(XPOS + 49, YPOS + 22); + lcd->Poke(XPOS + 50, YPOS + 22); + lcd->Poke(XPOS + 55, YPOS + 22); + lcd->Poke(XPOS + 56, YPOS + 22); + lcd->Poke(XPOS + 57, YPOS + 22); + lcd->Poke(XPOS + 58, YPOS + 22); + lcd->Poke(XPOS + 61, YPOS + 22); + lcd->Poke(XPOS + 62, YPOS + 22); + lcd->Poke(XPOS + 65, YPOS + 22); + lcd->Poke(XPOS + 66, YPOS + 22); + lcd->Poke(XPOS + 67, YPOS + 22); + lcd->Poke(XPOS + 72, YPOS + 22); + lcd->Poke(XPOS + 73, YPOS + 22); + lcd->Poke(XPOS + 74, YPOS + 22); + lcd->Poke(XPOS + 79, YPOS + 22); + lcd->Poke(XPOS + 80, YPOS + 22); + lcd->Poke(XPOS + 81, YPOS + 22); + lcd->Poke(XPOS + 84, YPOS + 22); + lcd->Poke(XPOS + 85, YPOS + 22); + lcd->Poke(XPOS + 86, YPOS + 22); + lcd->Poke(XPOS + 93, YPOS + 22); + lcd->Poke(XPOS + 94, YPOS + 22); + lcd->Poke(XPOS + 97, YPOS + 22); + lcd->Poke(XPOS + 98, YPOS + 22); + lcd->Poke(XPOS + 99, YPOS + 22); + lcd->Poke(XPOS + 105, YPOS + 22); + lcd->Poke(XPOS + 106, YPOS + 22); + lcd->Poke(XPOS + 107, YPOS + 22); + lcd->Poke(XPOS + 109, YPOS + 22); + lcd->Poke(XPOS + 110, YPOS + 22); + lcd->Poke(XPOS + 111, YPOS + 22); + lcd->Poke(XPOS + 117, YPOS + 22); + lcd->Poke(XPOS + 118, YPOS + 22); + lcd->Poke(XPOS + 119, YPOS + 22); + + lcd->Poke(XPOS + 4, YPOS + 23); + lcd->Poke(XPOS + 5, YPOS + 23); + lcd->Poke(XPOS + 6, YPOS + 23); + lcd->Poke(XPOS + 13, YPOS + 23); + lcd->Poke(XPOS + 14, YPOS + 23); + lcd->Poke(XPOS + 17, YPOS + 23); + lcd->Poke(XPOS + 18, YPOS + 23); + lcd->Poke(XPOS + 19, YPOS + 23); + lcd->Poke(XPOS + 28, YPOS + 23); + lcd->Poke(XPOS + 29, YPOS + 23); + lcd->Poke(XPOS + 36, YPOS + 23); + lcd->Poke(XPOS + 37, YPOS + 23); + lcd->Poke(XPOS + 38, YPOS + 23); + lcd->Poke(XPOS + 39, YPOS + 23); + lcd->Poke(XPOS + 42, YPOS + 23); + lcd->Poke(XPOS + 43, YPOS + 23); + lcd->Poke(XPOS + 44, YPOS + 23); + lcd->Poke(XPOS + 45, YPOS + 23); + lcd->Poke(XPOS + 48, YPOS + 23); + lcd->Poke(XPOS + 49, YPOS + 23); + lcd->Poke(XPOS + 50, YPOS + 23); + lcd->Poke(XPOS + 54, YPOS + 23); + lcd->Poke(XPOS + 55, YPOS + 23); + lcd->Poke(XPOS + 56, YPOS + 23); + lcd->Poke(XPOS + 57, YPOS + 23); + lcd->Poke(XPOS + 58, YPOS + 23); + lcd->Poke(XPOS + 61, YPOS + 23); + lcd->Poke(XPOS + 62, YPOS + 23); + lcd->Poke(XPOS + 65, YPOS + 23); + lcd->Poke(XPOS + 66, YPOS + 23); + lcd->Poke(XPOS + 67, YPOS + 23); + lcd->Poke(XPOS + 72, YPOS + 23); + lcd->Poke(XPOS + 73, YPOS + 23); + lcd->Poke(XPOS + 74, YPOS + 23); + lcd->Poke(XPOS + 79, YPOS + 23); + lcd->Poke(XPOS + 80, YPOS + 23); + lcd->Poke(XPOS + 81, YPOS + 23); + lcd->Poke(XPOS + 85, YPOS + 23); + lcd->Poke(XPOS + 86, YPOS + 23); + lcd->Poke(XPOS + 87, YPOS + 23); + lcd->Poke(XPOS + 92, YPOS + 23); + lcd->Poke(XPOS + 93, YPOS + 23); + lcd->Poke(XPOS + 94, YPOS + 23); + lcd->Poke(XPOS + 98, YPOS + 23); + lcd->Poke(XPOS + 99, YPOS + 23); + lcd->Poke(XPOS + 100, YPOS + 23); + lcd->Poke(XPOS + 104, YPOS + 23); + lcd->Poke(XPOS + 105, YPOS + 23); + lcd->Poke(XPOS + 106, YPOS + 23); + lcd->Poke(XPOS + 109, YPOS + 23); + lcd->Poke(XPOS + 110, YPOS + 23); + lcd->Poke(XPOS + 111, YPOS + 23); + lcd->Poke(XPOS + 117, YPOS + 23); + lcd->Poke(XPOS + 118, YPOS + 23); + lcd->Poke(XPOS + 119, YPOS + 23); + + lcd->Poke(XPOS + 5, YPOS + 25); + lcd->Poke(XPOS + 13, YPOS + 25); + lcd->Poke(XPOS + 14, YPOS + 25); + lcd->Poke(XPOS + 17, YPOS + 25); + lcd->Poke(XPOS + 18, YPOS + 25); + lcd->Poke(XPOS + 19, YPOS + 25); + lcd->Poke(XPOS + 29, YPOS + 25); + lcd->Poke(XPOS + 30, YPOS + 25); + lcd->Poke(XPOS + 31, YPOS + 25); + lcd->Poke(XPOS + 32, YPOS + 25); + lcd->Poke(XPOS + 38, YPOS + 25); + lcd->Poke(XPOS + 39, YPOS + 25); + lcd->Poke(XPOS + 40, YPOS + 25); + lcd->Poke(XPOS + 44, YPOS + 25); + lcd->Poke(XPOS + 45, YPOS + 25); + lcd->Poke(XPOS + 50, YPOS + 25); + lcd->Poke(XPOS + 51, YPOS + 25); + lcd->Poke(XPOS + 57, YPOS + 25); + lcd->Poke(XPOS + 58, YPOS + 25); + lcd->Poke(XPOS + 61, YPOS + 25); + lcd->Poke(XPOS + 62, YPOS + 25); + lcd->Poke(XPOS + 66, YPOS + 25); + lcd->Poke(XPOS + 73, YPOS + 25); + lcd->Poke(XPOS + 80, YPOS + 25); + lcd->Poke(XPOS + 87, YPOS + 25); + lcd->Poke(XPOS + 88, YPOS + 25); + lcd->Poke(XPOS + 89, YPOS + 25); + lcd->Poke(XPOS + 90, YPOS + 25); + lcd->Poke(XPOS + 91, YPOS + 25); + lcd->Poke(XPOS + 92, YPOS + 25); + lcd->Poke(XPOS + 100, YPOS + 25); + lcd->Poke(XPOS + 101, YPOS + 25); + lcd->Poke(XPOS + 102, YPOS + 25); + lcd->Poke(XPOS + 103, YPOS + 25); + lcd->Poke(XPOS + 104, YPOS + 25); + lcd->Poke(XPOS + 110, YPOS + 25); + lcd->Poke(XPOS + 111, YPOS + 25); + lcd->Poke(XPOS + 117, YPOS + 25); + lcd->Poke(XPOS + 118, YPOS + 25); + lcd->Poke(XPOS + 119, YPOS + 25); + + lcd->Poke(XPOS + 4, YPOS + 24); + lcd->Poke(XPOS + 5, YPOS + 24); + lcd->Poke(XPOS + 6, YPOS + 24); + lcd->Poke(XPOS + 13, YPOS + 24); + lcd->Poke(XPOS + 14, YPOS + 24); + lcd->Poke(XPOS + 17, YPOS + 24); + lcd->Poke(XPOS + 18, YPOS + 24); + lcd->Poke(XPOS + 19, YPOS + 24); + lcd->Poke(XPOS + 28, YPOS + 24); + lcd->Poke(XPOS + 29, YPOS + 24); + lcd->Poke(XPOS + 30, YPOS + 24); + lcd->Poke(XPOS + 31, YPOS + 24); + lcd->Poke(XPOS + 32, YPOS + 24); + lcd->Poke(XPOS + 33, YPOS + 24); + lcd->Poke(XPOS + 37, YPOS + 24); + lcd->Poke(XPOS + 38, YPOS + 24); + lcd->Poke(XPOS + 39, YPOS + 24); + lcd->Poke(XPOS + 40, YPOS + 24); + lcd->Poke(XPOS + 41, YPOS + 24); + lcd->Poke(XPOS + 42, YPOS + 24); + lcd->Poke(XPOS + 44, YPOS + 24); + lcd->Poke(XPOS + 45, YPOS + 24); + lcd->Poke(XPOS + 49, YPOS + 24); + lcd->Poke(XPOS + 50, YPOS + 24); + lcd->Poke(XPOS + 51, YPOS + 24); + lcd->Poke(XPOS + 54, YPOS + 24); + lcd->Poke(XPOS + 55, YPOS + 24); + lcd->Poke(XPOS + 56, YPOS + 24); + lcd->Poke(XPOS + 57, YPOS + 24); + lcd->Poke(XPOS + 58, YPOS + 24); + lcd->Poke(XPOS + 59, YPOS + 24); + lcd->Poke(XPOS + 61, YPOS + 24); + lcd->Poke(XPOS + 62, YPOS + 24); + lcd->Poke(XPOS + 65, YPOS + 24); + lcd->Poke(XPOS + 66, YPOS + 24); + lcd->Poke(XPOS + 67, YPOS + 24); + lcd->Poke(XPOS + 72, YPOS + 24); + lcd->Poke(XPOS + 73, YPOS + 24); + lcd->Poke(XPOS + 74, YPOS + 24); + lcd->Poke(XPOS + 79, YPOS + 24); + lcd->Poke(XPOS + 80, YPOS + 24); + lcd->Poke(XPOS + 81, YPOS + 24); + lcd->Poke(XPOS + 86, YPOS + 24); + lcd->Poke(XPOS + 87, YPOS + 24); + lcd->Poke(XPOS + 88, YPOS + 24); + lcd->Poke(XPOS + 89, YPOS + 24); + lcd->Poke(XPOS + 90, YPOS + 24); + lcd->Poke(XPOS + 91, YPOS + 24); + lcd->Poke(XPOS + 92, YPOS + 24); + lcd->Poke(XPOS + 93, YPOS + 24); + lcd->Poke(XPOS + 99, YPOS + 24); + lcd->Poke(XPOS + 100, YPOS + 24); + lcd->Poke(XPOS + 101, YPOS + 24); + lcd->Poke(XPOS + 102, YPOS + 24); + lcd->Poke(XPOS + 103, YPOS + 24); + lcd->Poke(XPOS + 104, YPOS + 24); + lcd->Poke(XPOS + 105, YPOS + 24); + lcd->Poke(XPOS + 109, YPOS + 24); + lcd->Poke(XPOS + 110, YPOS + 24); + lcd->Poke(XPOS + 111, YPOS + 24); + lcd->Poke(XPOS + 117, YPOS + 24); + lcd->Poke(XPOS + 118, YPOS + 24); + lcd->Poke(XPOS + 119, YPOS + 24); + + lcd->Flush(); + wait(2); + SC.changeScreen("menu"); + } +}; +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pantallas/ViajesGuardados.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,55 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#include "ViajesGuardados.h" + +extern ScreenManager SC; +extern SistemaArchivos SA; + +extern OpcionesViaje opcionesViaje; +extern OpcionesViaje opcionesViajeEN; + +extern DigitalOut myled; + +ViajesGuardados::ViajesGuardados(char newNoRides[]){ + strcpy(noRides, newNoRides); +} + +void ViajesGuardados::initialize(DogMLCD* lcd){ + ifContinuar = true; + // Se borran los elementos añadidos anteriormente + borrarElementos(); + // Se cargan los viajes guardados + SA.reloadRideNames(); + if(SA.getNrides() > 0){ // Si hay algún viaje guardado + // Se añaden a la lista de elementos los viajes guardados + for(int i = 0; i < SA.getNrides(); i++){ + addElement(SA.getNameRide(i), "rOptions"); + } + ListaSelec::initialize(lcd); + }else{ // Si no existe nigún viaje guardado + // Se muestra por pantalla un mensaje informándolo + // select font to use: + lcd->XFont = xfont_8; + + // Se desabilita el botón "continuar" + ifContinuar = false; + + // Se escribe el nombre + lcd->XString(OFFSETX, OFFSETY, noRides); + + // transmit work screen to physical screen: + lcd->Flush(); + } +} + +void ViajesGuardados::button5pressed(DogMLCD* lcd){ + // Se le pasa a la pantalla de menú del viaje el nombre del viaje seleccionado + opcionesViaje.setViaje(getElement(getSelect())); + opcionesViajeEN.setViaje(getElement(getSelect())); + + // Se llama a la función padre + if(ifContinuar){ + ListaSelec::button5pressed(lcd); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Pantallas/ViajesGuardados.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,25 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#ifndef VIAJESGUARDADOS_H +#define VIAJESGUARDADOS_H + +#include "ListaSelec.h" +#include "SistemaArchivos.h" +#include "OpcionesViaje.h" +#include "doggy.h" + +// Lista de elementos seleccionables. Tamaño de caracteres 8. +class ViajesGuardados: public ListaSelec{ + public: + ViajesGuardados(char newNoRides[]); + virtual void initialize(DogMLCD* lcd); + virtual void button5pressed(DogMLCD* lcd); // Esta función se llama cuando el botón central es pulsado, definirla para añadir funcionalidades + + private: + char noRides[MAXCARACTER8]; // Aviso de que no existen viajes guardados + bool ifContinuar; // Valdrá true si el botón continuar puede usarse para pasar al siguiente menú + +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RingBuffer/Buffering.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,91 @@ +#include "Buffering.h" + +Buffering::Buffering() +{ + for(int i = 0; i < BUFFERSIZE; i++){ + data[i] = 0; + } + windex = 0; + rindex = 0; + full = false; + empty = true; + bufSize = BUFFERSIZE; +} + +void Buffering::put(int16_t val) +{ + if(!full) + { + data[windex] = val; + windex++; + empty = false; + if(windex >= bufSize) + { + windex = 0; + } + if(getDif() >= bufSize - 1){ + full = true; + } + /*if(windex >= rindex) + { + full = true; + }*/ + } +} + +int16_t Buffering::get() +{ + int16_t temp = 0; + if(!empty) + { + temp = data[rindex]; + data[rindex] = 0; + full = false; + rindex++; + if(rindex >= bufSize) + { + rindex = 0; + } + if(getDif() == 0){ + empty = true; + } + /*if(rindex >= windex) + { + empty = true; + }*/ + } + return temp; +} + +bool Buffering::isFull() +{ + return full; +} + +bool Buffering::isEmpty() +{ + return empty; +} + +int Buffering::getSize() +{ + return bufSize; +} + +unsigned int Buffering::getWritingIndex() +{ + return windex; +} + +unsigned int Buffering::getReadingIndex() +{ + return rindex; +} + +unsigned int Buffering::getDif() +{ + unsigned int dif = 0; + if((int)(windex-rindex)>=0) { dif = windex-rindex; } + else { dif = bufSize+windex-rindex; } + return dif; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RingBuffer/Buffering.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,30 @@ +#ifndef BUFFERING_H +#define BUFFERING_H + +#include "mbed.h" + +#define BUFFERSIZE 600 +// Buffering de datos tipo float +class Buffering +{ +private: + int16_t data[BUFFERSIZE]; + unsigned int windex; + unsigned int rindex; + bool full; + bool empty; + unsigned int bufSize; +public: + Buffering(); + void put(int16_t val); + int16_t get(); + int getSize(); + bool isFull(); + bool isEmpty(); + unsigned int getWritingIndex(); + unsigned int getReadingIndex(); + unsigned int getDif(); +}; + +#endif // BUFFERING_H +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ScreenManager/ListaSelec.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,102 @@ +#include "mbed.h" +#include "ListaSelec.h" + +extern ScreenManager SC; + +extern DigitalIn boton1; +extern DigitalIn boton4; +extern DigitalIn boton5; + +void ListaSelec::DrawElements(DogMLCD* lcd){ + for(int i = 0; i < SCREENLINES; i++){ + if((i + topElement) < nElementos){ + lcd->XString(OFFSETX, HEIGHTCARACTER8*i + 1 + OFFSETY, list[i + topElement]); + } + } + drawSelection(OFFSETX-1, HEIGHTCARACTER8*posMark + OFFSETY, WIDTH-OFFSETX, HEIGHTCARACTER8, lcd); +} + +void ListaSelec::initialize(DogMLCD* lcd){ + // Se inicializa la selección + setSelect(0); + topElement = 0; + posMark = 0; + lastPosMark = 0; + + // select font to use: + lcd->XFont = xfont_8; + + // Se pintan los elementos de la lista + DrawElements(lcd); + + // transmit work screen to physical screen: + lcd->Flush(); +} + +// El botón 1 sube la selección al elemento superior al actual +void ListaSelec::button1pressed(DogMLCD* lcd){ + // Si sales de los elementos seleccionables no se cambia de selección + if((getSelect()-1) >= 0){ + // Se selecciona el elemento + setSelect(getSelect()-1); + // Si se ha seleccionado un elemento superior que no está siendo mostrado en la pantalla + if(getSelect() < topElement){ + // Se sube hacia arriba el top element (se le resta 1) y se pintan de nuevo los elementos de pantalla + topElement--; + lcd->Clear(); + DrawElements(lcd); + }else{ + // Sino se mueve el marcador de selección + lastPosMark = posMark; + posMark--; + drawDeselection(OFFSETX-1, HEIGHTCARACTER8*lastPosMark + OFFSETY, WIDTH-OFFSETX , HEIGHTCARACTER8, lcd); + drawSelection(OFFSETX-1, HEIGHTCARACTER8*posMark + OFFSETY, WIDTH-OFFSETX, HEIGHTCARACTER8, lcd); + } + // transmit work screen to physical screen: + lcd->Flush(); + } +} + +// El botón 4 baja la selección al elemento superior al actual +void ListaSelec::button4pressed(DogMLCD* lcd){ + // Si sales de los elementos seleccionables no se cambia de selección + if((getSelect()+1) <= (nElementos - 1)){ + // Se selecciona el elemento + setSelect(getSelect()+1); + // Si se ha seleccionado un elemento inferior que no está siendo mostrado en la pantalla + if(getSelect() > (topElement + SCREENLINES - 1)){ + lcd->Clear(); + topElement++; + DrawElements(lcd); + }else{ + // Sino se mueve el marcador de selección + lastPosMark = posMark; + posMark++; + drawDeselection(OFFSETX-1, HEIGHTCARACTER8*lastPosMark + OFFSETY, WIDTH-OFFSETX, HEIGHTCARACTER8, lcd); + drawSelection(OFFSETX-1, HEIGHTCARACTER8*posMark + OFFSETY, WIDTH-OFFSETX, HEIGHTCARACTER8, lcd); + } + // transmit work screen to physical screen: + lcd->Flush(); + } +} + + // El botón 5 envía a la pantalla correspondiente según el elemento seleccionado +void ListaSelec::button5pressed(DogMLCD* lcd){ + SC.changeScreen(nextScreenID[getSelect()]); +} + +// Añade un elemento al menu con el texto especificado en el primer argumento +// cada elemento nos enviará a la pantalla con el identificador del segundo argumento +// Devuelve el identificador del elemento añadido +int ListaSelec::addElement(char text[], char nameNextScreen[NCARSCREEN]){ + //strcpy(list[nElementos], text); + list[nElementos] = text; + //strcpy(nextScreenID[nElementos], nameNextScreen); + nextScreenID[nElementos] = nameNextScreen; + nElementos++; + return nElementos - 1; +} + +char *ListaSelec::getElement(int index){ + return list[index]; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ScreenManager/ListaSelec.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,41 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#ifndef LISTASELEC_H +#define LISTASELEC_H + +#include "Seleccion.h" +#include "doggy.h" + +#define OFFSETX 4 // Espacio en pixeles que se deja antes de escribir una linea de caracteres +#define OFFSETY 4 // Espacio en pixeles que se deja antes de escribir una linea de caracteres en la parte superior +#define MAXCARACTER8 19 // Número máximo de caracteres de cada elemento +#define HEIGHTCARACTER8 8 // Anchura de un caracter de media +#define SCREENLINES 7 // Número máximo de filas mostrados simultáneamente en pantalla +#define MAXLINES8 100 // Número máximo de filas (cada fila es un elemento) + +// Lista de elementos seleccionables. Tamaño de caracteres 8. +class ListaSelec: public Seleccion{ + public: + + virtual void initialize(DogMLCD* lcd); + int addElement(char text[], char nameNextScreen[NCARSCREEN]); + char *getElement(int index); + + void DrawElements(DogMLCD* lcd); // Pinta a partir del elemento superior, todos los que sea posible hasta ocupar la pantalla (valor de elementos dado por SCREENLINES) + + virtual void button1pressed(DogMLCD* lcd); // Esta función se llama cuando el botón superior es pulsado, definirla para añadir funcionalidades + virtual void button4pressed(DogMLCD* lcd); // Esta función se llama cuando el botón inferior es pulsado, definirla para añadir funcionalidades + virtual void button5pressed(DogMLCD* lcd); // Esta función se llama cuando el botón central es pulsado, definirla para añadir funcionalidades + + private: + //char list[MAXLINES8][MAXCARACTER8]; // Lista con las opciones seleccionables + char *list[MAXLINES8]; // Lista con las opciones seleccionables + char *nextScreenID[MAXLINES8]; // Guarda el nombre de las pantallas a la que debe dirigirse si se elige un elemento + //char nextScreenID[MAXLINES8][NCARSCREEN]; // Guarda el nombre de las pantallas a la que debe dirigirse si se elige un elemento + int topElement; + int posMark; // Posicion del marcador de seleccion + int lastPosMark; // Últim posición del marcador de seleccion +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ScreenManager/Mensaje.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,70 @@ +#include "mbed.h" +#include "Mensaje.h" + +extern ScreenManager SC; +extern DigitalIn boton5; + +Mensaje::Mensaje(char nextScreen[], char newAdvice[]){ + strcpy(nextScreenID, nextScreen); + strcpy(advice, newAdvice); +} + +void Mensaje::setNextScreen(char nameScreen[NCARSCREEN]){ + strcpy(nextScreenID, nameScreen); +} + +void Mensaje::initialize(DogMLCD* lcd){ + + // select font to use: + lcd->XFont = xfont_11; + + // Para pintar los elementos del menú primero + // se calcula la posición del primer elemento y el offset hasta el siguiente elemento (eje vertical) + int offset = HEIGHT/(nElementos + 1); + int posy0 = offset - SEMIHEIGHTFONT; + + // Se pintan los elementos del menu con dos particularidades: + // - El elemento seleccionado se pinta "seleccionado" + // - Los elementos se pintan centrados + + for(int i = 0; i < nElementos; i++){ + posElement[i][2] = widthElement(i, lcd); + posElement[i][0] = (WIDTH - posElement[i][2])/2; + posElement[i][1] = offset*(i) + posy0;; + lcd->XString(posElement[i][0], posElement[i][1], list[i]); + } + + // select font to use: + lcd->XFont = xfont_8; + + // Se escribe el consejo en la parte inferior de la pantalla + lcd->XString(OFFSETX, HEIGHT - 8, advice); + + // transmit work screen to physical screen: + lcd->Flush(); +} + +// El botón 5 envía a la pantalla correspondiente según el elemento seleccionado +void Mensaje::button5pressed(DogMLCD* lcd){ + SC.changeScreen(nextScreenID); +} + +// Añade un elemento al menu con el texto especificado en el primer argumento +// cada elemento nos enviará a la pantalla con el identificador del segundo argumento +// Devuelve el identificador del elemento añadido +int Mensaje::addElement(char text[]){ + strcpy(list[nElementos], text); + nElementos++; + return nElementos - 1; +} + + +// Devuelve el ancho del elemento +// Para ello lo recorre sumando los pixeles que ocupa cada caracter +int Mensaje::widthElement(int element, DogMLCD* lcd){ + int width = 0; + for(int i = 0; i < (strlen(list[element])); i++){ + width += lcd->GetGlyph(list[element][i]).wid + 1; + } + return width; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ScreenManager/Mensaje.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,40 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#ifndef MENSAJE_H +#define MENSAJE_H + +#include "Seleccion.h" +#include "doggy.h" + +#define SEMIHEIGHTFONT 5 // La mitad de la altura de un caracter +#define MAXCARACTER 28 // Número máximo de caracteres de cada elemento +#define HEIGHTCARACTER 11 // Anchura de un caracter de media +#define MAXLINES 5 // Número máximo de filas (cada fila es un elemento) +#define OFFSETX 4 // Espacio en pixeles que se deja antes de escribir una linea de caracteres + +// EL menu es una lista de selección con los elementos equiespeciados, no centrados en la esquina superior izquierda +// como en una lista de selección normal. Además el texto es de tamaño 11. +class Mensaje : public Seleccion { + public: + Mensaje(char nextScreen[], char newAdvice[]); + + void setNextScreen(char nameScreen[NCARSCREEN]); + + virtual void initialize(DogMLCD* lcd); + int addElement(char text[]); + + virtual void button5pressed(DogMLCD* lcd); // Esta función se llama cuando el botón central es pulsado, definirla para añadir funcionalidades + + private: + char list[MAXLINES][MAXCARACTER]; // Lista con las opciones del menu. Pueden ser com máximo 5 con una longitud máxima de 24 caracteres + int posElement[MAXLINES][3]; // Guarda las posición y tamaños de cada elemento (0 = posx, 1 = posy, 2 = ancho) + char nextScreenID[NCARSCREEN]; + char advice[MAXCARACTER]; + + // Devuelve el ancho del elemento + // Para ello lo recorre sumando los pixeles que ocupa cada caracter + int widthElement(int element, DogMLCD* lcd); +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ScreenManager/Menu.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,90 @@ +#include "mbed.h" +#include "Menu.h" + +extern ScreenManager SC; + +extern DigitalIn boton1; +extern DigitalIn boton4; +extern DigitalIn boton5; + +void Menu::initialize(DogMLCD* lcd){ + // Se inicializa la selección + setSelect(0); + + // select font to use: + lcd->XFont = xfont_11; + + // Para pintar los elementos del menú primero + // se calcula la posición del primer elemento y el offset hasta el siguiente elemento (eje vertical) + int offset = HEIGHT/(nElementos + 1); + int posy0 = offset - SEMIHEIGHTFONT; + + // Se pintan los elementos del menu con dos particularidades: + // - El elemento seleccionado se pinta "seleccionado" + // - Los elementos se pintan centrados + + for(int i = 0; i < nElementos; i++){ + posElement[i][2] = widthElement(i, lcd); + posElement[i][0] = (WIDTH - posElement[i][2])/2; + posElement[i][1] = offset*(i) + posy0;; + lcd->XString(posElement[i][0], posElement[i][1], list[i]); + // Si el elemento está seleccionado se marca con la forma de selección correspondiente + if(i == getSelect()){ + drawSelection(posElement[i][0]-2, posElement[i][1]-1, posElement[i][2]+2, HEIGHTCARACTER+2, lcd); + } + } + + // transmit work screen to physical screen: + lcd->Flush(); +} + +// El botón 1 sube la selección al elemento superior al actual +void Menu::button1pressed(DogMLCD* lcd){ + // Si sales de los elementos seleccionables no se cambia de selección + if((getSelect()-1) >= 0){ + setSelect(getSelect()-1); + drawDeselection(posElement[getLastSelect()][0]-2, posElement[getLastSelect()][1]-1, posElement[getLastSelect()][2]+2, HEIGHTCARACTER+2, lcd); + drawSelection(posElement[getSelect()][0]-2, posElement[getSelect()][1]-1, posElement[getSelect()][2]+2, HEIGHTCARACTER+2, lcd); + // transmit work screen to physical screen: + lcd->Flush(); + } +} + +// El botón 4 baja la selección al elemento superior al actual +void Menu::button4pressed(DogMLCD* lcd){ + // Si sales de los elementos seleccionables no se cambia de selección + if((getSelect()+1) <= (nElementos - 1)){ + setSelect(getSelect()+1); + drawDeselection(posElement[getLastSelect()][0]-2, posElement[getLastSelect()][1]-1, posElement[getLastSelect()][2]+2, HEIGHTCARACTER+2, lcd); + drawSelection(posElement[getSelect()][0]-2, posElement[getSelect()][1]-1, posElement[getSelect()][2]+2, HEIGHTCARACTER+2, lcd); + // transmit work screen to physical screen: + lcd->Flush(); + } +} + +// El botón 5 envía a la pantalla correspondiente según el elemento seleccionado +void Menu::button5pressed(DogMLCD* lcd){ + SC.changeScreen(nextScreenID[getSelect()]); +} + +// Añade un elemento al menu con el texto especificado en el primer argumento +// cada elemento nos enviará a la pantalla con el identificador del segundo argumento +// Devuelve el identificador del elemento añadido +int Menu::addElement(char text[], char nameNextScreen[NCARSCREEN]){ + strcpy(list[nElementos], text); + strcpy(nextScreenID[nElementos], nameNextScreen); + nElementos++; + return nElementos - 1; +} + + +// Devuelve el ancho del elemento +// Para ello lo recorre sumando los pixeles que ocupa cada caracter +int Menu::widthElement(int element, DogMLCD* lcd){ + int width = 0; + for(int i = 0; i < (strlen(list[element])); i++){ + width += lcd->GetGlyph(list[element][i]).wid + 1; + } + return width; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ScreenManager/Menu.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,39 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#ifndef MENU_H +#define MENU_H + +#include "Seleccion.h" +#include "doggy.h" + + +#define SEMIHEIGHTFONT 5 // La mitad de la altura de un caracter +#define MAXCARACTER 22 // Número máximo de caracteres de cada elemento +#define HEIGHTCARACTER 11 // Anchura de un caracter de media +#define MAXLINES 5 // Número máximo de filas (cada fila es un elemento) +#define OFFSETX 4 // Espacio en pixeles que se deja antes de escribir una linea de caracteres +#define OFFSETY 4 // Espacio en pixeles que se deja antes de escribir una linea de caracteres en la parte superior + +// EL menu es una lista de selección con los elementos equiespeciados, no centrados en la esquina superior izquierda +// como en una lista de selección normal. Además el texto es de tamaño 11. +class Menu : public Seleccion { + public: + virtual void initialize(DogMLCD* lcd); + int addElement(char text[], char nameNextScreen[NCARSCREEN]); + + virtual void button1pressed(DogMLCD* lcd); // Esta función se llama cuando el botón superior es pulsado, definirla para añadir funcionalidades + virtual void button4pressed(DogMLCD* lcd); // Esta función se llama cuando el botón inferior es pulsado, definirla para añadir funcionalidades + virtual void button5pressed(DogMLCD* lcd); // Esta función se llama cuando el botón central es pulsado, definirla para añadir funcionalidades + + private: + char list[MAXLINES][MAXCARACTER]; // Lista con las opciones del menu. Pueden ser com máximo 5 con una longitud máxima de 24 caracteres + int posElement[5][3]; // Guarda las posición y tamaños de cada elemento (0 = posx, 1 = posy, 2 = ancho) + char nextScreenID[5][NCARSCREEN]; + + // Devuelve el ancho del elemento + // Para ello lo recorre sumando los pixeles que ocupa cada caracter + int widthElement(int element, DogMLCD* lcd); +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ScreenManager/Screen.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,15 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ + +#include "doggy.h" + +#define WIDTH 128 +#define HEIGHT 64 + +class Screen { + +public: + virtual void initialize(DogMLCD* lcd){} + virtual void update(DogMLCD* lcd){} +}; \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ScreenManager/ScreenManager.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,73 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ + +#include "ScreenManager.h" + +ScreenManager::ScreenManager(DogMLCD* lcdScreen){ + currentGroupID = 0; + currentScreen = 0; + lastScreen = 0; + for(int i = 0; i < NIDIOMAS; i++){ + nScreens[i] = 0; + } + lcd = lcdScreen; +} + +void ScreenManager::selectGroup(int groupID){ + currentGroupID = groupID; +} + +int ScreenManager::addScreen(Screen* screen, char name[16], int groupID){ // Devuelve el índice asignado a la nueva pantalla + screens[groupID][nScreens[groupID]] = screen; + strcpy(screenName[groupID][nScreens[groupID]],name); + nScreens[groupID]++; + return nScreens[groupID] - 1; +} + +void ScreenManager::changeScreen(char nameNextScreen[16]){ + // se busca el identificador numérico de la lista de pantallas según el nombre pasado a la función + // para ello se recorre la lista de pantallas + int nextScreen; + for(int i = 0; i < nScreens[currentGroupID]; i++){ + if(strcmp(nameNextScreen, screenName[currentGroupID][i]) == 0){ + nextScreen = i; + } + } + // Se selecciona la siguiente pantala + lastScreen = currentScreen; + currentScreen = nextScreen; + // Se borra la pantalla para dejar paso a la pantalla siguiente + lcd->Clear(); + lcd->Flush(); + // Se inicializa la pantalla siguiente + screens[currentGroupID][currentScreen]->initialize(lcd); +} + +char *ScreenManager::getCurrentScreen(){ + return screenName[currentGroupID][currentScreen]; +} + +int ScreenManager::getnScreen(int groupID){ + return nScreens[groupID]; +} + +void ScreenManager::getLastScreen(char buff[]){ + strcpy(buff, screenName[currentGroupID][lastScreen]); +} + +int ScreenManager::getCurrentGroupID(){ + return currentGroupID; +} + +void ScreenManager::backScreen(){ + changeScreen(screenName[currentGroupID][lastScreen]); +} + +void ScreenManager::initialize(){ + screens[currentGroupID][currentScreen]->initialize(lcd); +} + +void ScreenManager::update(){ + screens[currentGroupID][currentScreen]->update(lcd); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ScreenManager/ScreenManager.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,47 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#ifndef SCREENMANAGER_H +#define SCREENMANAGER_H + +#define NUMSCREENS 25 +#define NIDIOMAS 2 +#define NCARSCREEN 16 + +#include "Screen.cpp" +#include <string.h> + +class ScreenManager { + +public: + /** + * Constructor. + * + */ + ScreenManager(DogMLCD* lcdScreen); + + void selectGroup(int groupID); // Se selecciona el grupo mostrado actualmente. Llamamar a esta funcioón justo antes de cambiar a una pantalla o llamar initialize para que se muestre la actual correctamente + int addScreen(Screen* screen, char name[NCARSCREEN], int groupID); // Devuelve el índice asignado a la nueva pantalla + void changeScreen(char nameNextScreen[NCARSCREEN]); + void backScreen(); // Vuelve a la pantalla anterior, devuelve el índice de la pantalla anterior + void getLastScreen(char buff[]); // Devuelve el nombre de la pantalla anterior + int getnScreen(int groupID); // Devuelve el número de pantallas + int getCurrentGroupID(); //Devuelve el grupo de patallas seleccionado actual + char *getCurrentScreen(); // Devuelve el nombre de la pantalla actual + + void initialize(); // Iniciliza la pantalla actual + void update(); + + + private: + int currentGroupID; // Grupo actual + int currentScreen; // Índice de la pantalla actual + int lastScreen; // Índice de la pantalla anterior + int nScreens[NIDIOMAS]; // Número total de pantallas añadidas de cada grupo + Screen* screens[NIDIOMAS][NUMSCREENS]; + char screenName[NIDIOMAS][NUMSCREENS][NCARSCREEN]; + DogMLCD* lcd; + +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ScreenManager/SelecManager.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,27 @@ +#include "SelecManager.h" + +SelecManager::SelecManager(){ + nScreens = 0; +} + +int SelecManager::addScreen(Seleccion *screen){ + screens[nScreens] = screen; + nScreens++; + return nScreens -1; +} + +void SelecManager::setInverterSelection(){ + for(int i = 0; i < nScreens; i++){ + screens[i]->setInverterSelection(); + } +} + +void SelecManager::setRectSelection(){ + for(int i = 0; i < nScreens; i++){ + screens[i]->setRectSelection(); + } +} + +int SelecManager::getnScreens(){ + return nScreens; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ScreenManager/SelecManager.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,34 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#ifndef SELECMANAGER_H +#define SELECMANAGER_H + +#define NSELECSCREEN 25 // Número máximo de pantallas seleccionables + +#include "Seleccion.h" + +// Esta clase se encarga de gestionar los elementos comunes de las pantallas con elementos seleecionables como por ejemplo la forma de selección +class SelecManager { + +public: + /** + * Constructor. + * + */ + SelecManager(); + + int addScreen(Seleccion* screen); // Devuelve el número de identificación en la lista de pantallas seleccionables + + void setInverterSelection(); // Configura la forma de selección de inversión de pixeles del elemento + + void setRectSelection(); // Configura la forma de selección mediante rectángulos delimitadores + + int getnScreens(); + +private: + int nScreens; + Seleccion* screens[NSELECSCREEN]; // Lista de pantallas seleccionables +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ScreenManager/Seleccion.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,168 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#include "Seleccion.h" + +extern ScreenManager SC; + +extern DigitalIn boton1; +extern DigitalIn boton2; +extern DigitalIn boton3; +extern DigitalIn boton4; +extern DigitalIn boton5; +extern DigitalIn boton6; + +Seleccion::Seleccion(){ + // Se inicializan las variables + invType = true; + nElementos = 0; + select = 0; + lastSelect = 0; + pulsado1 = false; + pulsado2 = false; + pulsado3 = false; + pulsado4 = false; + pulsado5 = false; + pulsado6 = false; + backScreen = false; +} + +void Seleccion::borrarElementos(){ + // para borrar los elementos existentes sólo hay que reiniciar el número de elementos + nElementos = 0; +} + +void Seleccion::setInverterSelection(){ + invType = true; +} + +void Seleccion::setRectSelection(){ + invType = false; +} + +int Seleccion::getSelect(){ + return select; +} + +void Seleccion::setSelect(int newSelect){ + lastSelect = select; + select = newSelect; +} + +int Seleccion::getLastSelect(){ + return lastSelect; +} + +bool Seleccion::getSelectType(){ + return invType; +} + +void Seleccion::drawSelection(int x, int y, int width, int height, DogMLCD* lcd){ + // Se pinta de distinta manera dependiendo de la forma de selección + if(invType){ + lcd->InvRect(x, y, x+width, y+height); + }else{ + lcd->Frame(x, y, x+width, y+height); + } +} + +void Seleccion::drawDeselection(int x, int y, int width, int height, DogMLCD* lcd){ + // Se pinta de distinta manera dependiendo de la forma de selección + if(invType){ + lcd->InvRect(x, y, x+width, y+height); + }else{ + lcd->Frame(x, y, x+width, y+height, wipe); + } +} + +// En esta función se comprueba si se han pulsado los botones +void Seleccion::update(DogMLCD* lcd){ + if(boton1 == 1){ + // Se espera a que se suelte el botón + pulsado1 = true; + }else{ + if(pulsado1 == true){ + // Antes de cambiar de pantalla se llama la siguiente funcion con la que se puede añadir funcionalidad + button1pressed(lcd); + // Se inicializa la variable que controla la pulsación + pulsado1 = false; + } + } + if(boton2 == 1){ + // Se espera a que se suelte el botón + pulsado2 = true; + }else{ + if(pulsado2 == true){ + // Antes de cambiar de pantalla se llama la siguiente funcion con la que se puede añadir funcionalidad + button2pressed(lcd); + // Se inicializa la variable que controla la pulsación + pulsado2 = false; + } + } + if(boton3 == 1){ + // Se espera a que se suelte el botón + pulsado3 = true; + }else{ + if(pulsado3 == true){ + // Antes de cambiar de pantalla se llama la siguiente funcion con la que se puede añadir funcionalidad + button3pressed(lcd); + // Se inicializa la variable que controla la pulsación + pulsado3 = false; + } + } + if(boton4 == 1){ + // Se espera a que se suelte el botón + pulsado4 = true; + }else{ + if(pulsado4 == true){ + // Antes de cambiar de pantalla se llama la siguiente funcion con la que se puede añadir funcionalidad + button4pressed(lcd); + // Se inicializa la variable que controla la pulsación + pulsado4 = false; + } + } + if(boton5 == 1){ + // Se espera a que se suelte el botón + pulsado5 = true; + }else{ + if(pulsado5 == true){ + // Antes de cambiar de pantalla se llama la siguiente funcion con la que se puede añadir funcionalidad + button5pressed(lcd); + // Se inicializa la variable que controla la pulsación + pulsado5 = false; + } + } + if(boton6 == 1){ + // Se espera a que se suelte el botón + pulsado6 = true; + }else{ + if(pulsado6 == true){ + // Antes de cambiar de pantalla se llama la siguiente funcion con la que se puede añadir funcionalidad + button6pressed(lcd); + // Se inicializa la variable que controla la pulsación + pulsado6 = false; + } + } +} + +// Esta función guarda la pantalla a la que se debe volver en caso de ser pulsado el boton atras +void Seleccion::setBackScreen(char nameScreen[NCARSCREEN]){ + strcpy(nameBackScreen, nameScreen); + backScreen = true; +} + +// Esta función desactiva volver a la pantalla anterior (si la pantalla no vuelve a ninguna pantalla debe usarse) +void Seleccion::disableBackScreen(){ + backScreen = false; +} + +void Seleccion::button1pressed(DogMLCD* lcd){} +void Seleccion::button2pressed(DogMLCD* lcd){} +void Seleccion::button3pressed(DogMLCD* lcd){} +void Seleccion::button4pressed(DogMLCD* lcd){} +void Seleccion::button5pressed(DogMLCD* lcd){} +void Seleccion::button6pressed(DogMLCD* lcd){ + if(backScreen){ + SC.changeScreen(nameBackScreen); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ScreenManager/Seleccion.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,63 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#ifndef SELECCION_H +#define SELECCION_H + +#include "ScreenManager.h" +#include "doggy.h" + +// Esta clase es la base de pantallas en las que haya objetos sleccionables +// como menus o listas +class Seleccion: public Screen { + + public: + int nElementos; // Número de elementos en la lista de selección + + void borrarElementos(); // Borra los elementos existentes + + Seleccion(); + + virtual void update(DogMLCD* lcd); + + void setInverterSelection(); + + void setRectSelection(); + + int getSelect(); + + void setSelect(int newSelect); // Se selecciona un elemento + + int getLastSelect(); + + bool getSelectType(); + + void drawSelection(int x, int y, int width, int height, DogMLCD* lcd); + + void drawDeselection(int x, int y, int width, int height, DogMLCD* lcd); + + virtual void button1pressed(DogMLCD* lcd); // Esta función se llama cuando el botón superior es pulsado, definirla para añadir funcionalidades + virtual void button2pressed(DogMLCD* lcd); // Esta función se llama cuando el botón izquierdo es pulsado, definirla para añadir funcionalidades + virtual void button3pressed(DogMLCD* lcd); // Esta función se llama cuando el botón derecho es pulsado, definirla para añadir funcionalidades + virtual void button4pressed(DogMLCD* lcd); // Esta función se llama cuando el botón inferior es pulsado, definirla para añadir funcionalidades + virtual void button5pressed(DogMLCD* lcd); // Esta función se llama cuando el botón central es pulsado, definirla para añadir funcionalidades + virtual void button6pressed(DogMLCD* lcd); // Esta función se llama cuando el botón atras es pulsado, definirla para añadir funcionalidades + char nameBackScreen[NCARSCREEN]; + bool backScreen; // true si existe pagina atras, sino no se puede volver a la página anterior pulsando el boton correspondiente + void setBackScreen(char nameScreen[NCARSCREEN]); + void disableBackScreen(); + + private: + int select; // Elemento seleccionado de la lista de elementos + int lastSelect; // Anterior elemento seleccionado + bool invType; // Indica el tipo de selección. true: invirtiendo, false: pintando un recuadro + + bool pulsado1; + bool pulsado2; + bool pulsado3; + bool pulsado4; + bool pulsado5; + bool pulsado6; +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ScreenManager/Teclado.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,465 @@ +#include "mbed.h" +#include "Teclado.h" + +extern ScreenManager SC; + +extern DigitalIn boton1; +extern DigitalIn boton2; +extern DigitalIn boton3; +extern DigitalIn boton4; +extern DigitalIn boton5; + +extern DigitalOut myled; + +void Teclado::initialize(DogMLCD* lcd){ + // Se inicializa la variable que guarda el último nombre introducido + for(int i = 0; i < MAXCARACTERESESCRITURA; i++){ + nombre[i] = 0; + } + + // Se inicializa la selección + setSelect(0); + + indiceEscritura = 0; + + mostrarRecuadro(lcd); + + // Por defecto se muestran caracteres de letras minusculas + asignarMinusculas(); + ifMayus = false; + + // Se muestran los caracteres normales + mostrarCaracteres(lcd); + + // Se muestran los caracteres especiales + mostrarEspeciales(lcd); + + // Se inicializa la selección + Xsel = 0; + Ysel = 0; + lastXsel = 0; + lastYsel = 0; + // Se pinta la selección por defecto + drawSelection(OFFSETX-2, WRITTENSPACE, CARACTER11, CARACTER11, lcd); + + // transmit work screen to physical screen: + lcd->Flush(); + +} + +// El botón 5 envía a la pantalla correspondiente según el elemento seleccionado +void Teclado::button5pressed(DogMLCD* lcd){ + + // Si no es una tecla especial + if(m[Ysel][Xsel] > ULTIMOCARACTERESPECIAL){ + // select font to use: + lcd->XFont = xfont_8; + if(indiceEscritura < MAXCARACTERESESCRITURA){ + // Si se ha pulsado sobre un caracter normal se añade este al recuadro donde se muestra lo escrito + if(m[Ysel][Xsel] > ULTIMOCARACTERESPECIAL){ // Si el elemento no es un caracter o tecla especial + // Se asigna el caracter en la cedena + nombre[indiceEscritura] = m[Ysel][Xsel]; + indiceEscritura++; + // Se actualiza el caracter finde cadena + if(indiceEscritura < MAXCARACTERESESCRITURA){ + nombre[indiceEscritura] = '\0'; + } + + // Se borra la cadena mostrada actualmente + lcd->Rect(POSCADENAX,1,WIDTH-2, WRITTENSPACE-2, DOGMLCD_full, wipe); + + // Se escribe la nueva cadena + lcd->XString(POSCADENAX, 1, nombre); + } + } + }else{ // Teclas especiales + if(m[Ysel][Xsel] == SPACEBAR){ // Barra espaciadora + // Se aplica un espacio + nombre[indiceEscritura] = ' '; + indiceEscritura++; + // Se actualiza el caracter fin de cadena + if(indiceEscritura < MAXCARACTERESESCRITURA){ + nombre[indiceEscritura] = '\0'; + } + }else if(m[Ysel][Xsel] == MAYUS){ + // Se intercambian los caracteres actuales mayúsculas/minúculas + // Primero se limpia la pantalla + lcd->Clear(); + mostrarRecuadro(lcd); + // Se asignan los caracteres que corresponden + if(ifMayus){ + asignarMinusculas(); + ifMayus = false; + }else{ + asignarMayusculas(); + ifMayus = true; + } + // Se muestran los caracteres normales + mostrarCaracteres(lcd); + + // Se muestran los caracteres especiales + mostrarEspeciales(lcd); + + // Se escribe la selección del mayus + drawSelection(OFFSETX-2 + Xsel*CARACTER11, WRITTENSPACE + Ysel*CARACTER11, CARACTER11, CARACTER11-1, lcd); + + // select font to use: + lcd->XFont = xfont_8; + + // Se escribe la nueva cadena + lcd->XString(POSCADENAX, 1, nombre); + + // transmit work screen to physical screen: + lcd->Flush(); + }else if(m[Ysel][Xsel] == BACK){ + // Se borra el último caracter de la cadena escribiendo en su lugar un caracter fin de cadena + if(indiceEscritura > 0){ // Si hay algo que borrar + indiceEscritura--; + nombre[indiceEscritura] = '\0'; + + // Se borra la cadena mostrada actualmente + lcd->Rect(POSCADENAX,1,WIDTH-2, WRITTENSPACE-2, DOGMLCD_full, wipe); + + // Se escribe la nueva cadena + lcd->XString(POSCADENAX, 1, nombre); + } + }else if(m[Ysel][Xsel] == APLICAR){ + SC.changeScreen(nameNextScreen); + } + } + + // transmit work screen to physical screen: + lcd->Flush(); +} + +void Teclado::mostrarEspeciales(DogMLCD* lcd){ + // Se pinta la flecha de borrado de caracteres + lcd->Rect(OFFSETX + CARACTER11*10 + 2, WRITTENSPACE + CARACTER11*3 + 3, OFFSETX + CARACTER11*10 + 2 + 6, WRITTENSPACE + CARACTER11*3 + 3 + 5); + lcd->LineV(OFFSETX + CARACTER11*10 + 1, WRITTENSPACE + CARACTER11*3 + 4, WRITTENSPACE + CARACTER11*3 + 7); + lcd->LineV(OFFSETX + CARACTER11*10, WRITTENSPACE + CARACTER11*3 + 5, WRITTENSPACE + CARACTER11*3 + 6); + + // Se pinta la flecha de mayus + lcd->Rect(OFFSETX + 2, WRITTENSPACE + CARACTER11*4 + 5, OFFSETX + 2 + 3, WRITTENSPACE + CARACTER11*4 + 5 + 4); + lcd->LineH(OFFSETX + 1, WRITTENSPACE + CARACTER11*4 + 4, OFFSETX + 1 + 5); + lcd->LineH(OFFSETX + 2, WRITTENSPACE + CARACTER11*4 + 3, OFFSETX + 2 + 3); + lcd->LineH(OFFSETX + 3, WRITTENSPACE + CARACTER11*4 + 2, OFFSETX + 3 + 1); + + // Se pinta el intro (abarca el espacio de dos elementos de la matriz) + lcd->Rect(OFFSETX + CARACTER11*10 + 5, WRITTENSPACE + CARACTER11*4 + 1, OFFSETX + CARACTER11*10 + 5 + 2, WRITTENSPACE + CARACTER11*4 + 5); + lcd->Rect(OFFSETX + CARACTER11*9 + 3, WRITTENSPACE + CARACTER11*4 + 6, OFFSETX + CARACTER11*9 + 3 + 15, WRITTENSPACE + CARACTER11*4 + 6 + 2); + lcd->LineV(OFFSETX + CARACTER11*9 + 2, WRITTENSPACE + CARACTER11*4 + 5, WRITTENSPACE + CARACTER11*4 + 5 + 4); + lcd->LineV(OFFSETX + CARACTER11*9 + 1, WRITTENSPACE + CARACTER11*4 + 6, WRITTENSPACE + CARACTER11*4 + 6 + 2); + lcd->LineV(OFFSETX + CARACTER11*9 , WRITTENSPACE + CARACTER11*4 + 7, WRITTENSPACE + CARACTER11*4 + 7); + + // Se pinta la barra espaciadora (abarca el espacio de 8 elementos de la matriz) + lcd->Rect(OFFSETX + CARACTER11 + 3, WRITTENSPACE + CARACTER11*4 + 6, OFFSETX + CARACTER11 + 79, WRITTENSPACE + CARACTER11*4 + 6 + 1); + lcd->Rect(OFFSETX + CARACTER11 + 3, WRITTENSPACE + CARACTER11*4 + 2, OFFSETX + CARACTER11 + 3 + 1, WRITTENSPACE + CARACTER11*4 + 2 + 3); + lcd->Rect(OFFSETX + CARACTER11 + 78, WRITTENSPACE + CARACTER11*4 + 2, OFFSETX + CARACTER11 + 79, WRITTENSPACE + CARACTER11*4 + 2 + 3); +} + +void Teclado::seleccionarAplicar(DogMLCD* lcd){ + drawSelection(OFFSETX + CARACTER11 + 84, WRITTENSPACE + CARACTER11*4, 24, 10, lcd); +} + +void Teclado::deseleccionarAplicar(DogMLCD* lcd){ + drawDeselection(OFFSETX + CARACTER11 + 84, WRITTENSPACE + CARACTER11*4, 24, 10, lcd); +} + +void Teclado::seleccionarBarraEspaciadora(DogMLCD* lcd){ + drawSelection(OFFSETX + CARACTER11 - 1, WRITTENSPACE + CARACTER11*4, 84, 10, lcd); +} + +void Teclado::deseleccionarBarraEspaciadora(DogMLCD* lcd){ + drawDeselection(OFFSETX + CARACTER11 - 1, WRITTENSPACE + CARACTER11*4, 84, 10, lcd); +} + +void Teclado::mostrarCaracteres(DogMLCD* lcd){ + // select font to use: + lcd->XFont = xfont_11; + + // Se recorre la matriz mostrando todo lo que no sean caracteres o teclas especiales + for(int i = 0; i < FILASMATRIZ; i++){ + for(int j = 0; j < COLUMNASMATRIZ; j++){ + if(m[i][j] > ULTIMOCARACTERESPECIAL){ // SI el elemento no es un caracter o tecla especial + // se muestra + lcd->XChar(OFFSETX + CARACTER11*j, WRITTENSPACE + CARACTER11*i, m[i][j]); + } + } + } +} + +void Teclado::mostrarRecuadro(DogMLCD* lcd){ + lcd->Frame(0, 0,WIDTH-1, WRITTENSPACE-1); +} + +// El botón 1 sube la selección al elemento superior al actual +void Teclado::button1pressed(DogMLCD* lcd){ + // Si sales de los elementos seleccionables no se cambia de selección + if((Ysel - 1) >= 0){ + // Si se venía de la última fila (teclas especiales) + if(Ysel == (FILASMATRIZ-1) ){ + // Si se venía la barra espaciadora se selecciona esta + if(m[Ysel][Xsel] == SPACEBAR){ + deseleccionarBarraEspaciadora(lcd); + }else if(m[Ysel][Xsel] == APLICAR){ // Si se venía de la tecla aplicar se selecciona esta + deseleccionarAplicar(lcd); + }else{ + // se venía del mayus mayus + drawDeselection(OFFSETX-2 + Xsel*CARACTER11, WRITTENSPACE + Ysel*CARACTER11, CARACTER11, CARACTER11-1, lcd); + } + }else{ + // Se deselecciona la tecla anterior + drawDeselection(OFFSETX-2 + Xsel*CARACTER11, WRITTENSPACE + Ysel*CARACTER11, CARACTER11, CARACTER11, lcd); + } + + // Se selecciona el nuevo elemento + Ysel--; + + // Se escribe la nueva selección + drawSelection(OFFSETX-2 + Xsel*CARACTER11, WRITTENSPACE + Ysel*CARACTER11, CARACTER11, CARACTER11, lcd); + + // transmit work screen to physical screen: + lcd->Flush(); + } +} + +// El botón 2 desplaza la selección al elemento izquierdo al actual +void Teclado::button2pressed(DogMLCD* lcd){ + // Si sales de los elementos seleccionables no se cambia de selección + if((Xsel - 1) >= 0){ + // Si se está en la última fila + if(Ysel == (FILASMATRIZ-1) ){ + // Se se venía de la tecla aplicar + if(m[Ysel][Xsel] == APLICAR){ + deseleccionarAplicar(lcd); + seleccionarBarraEspaciadora(lcd); + // Se mueven dos elementos a la izquierda + Xsel -= 2; + }else{ + deseleccionarBarraEspaciadora(lcd); + // Se mueve la selección al elemento de la izquierda + Xsel = 0; + // Se escribe la nueva selección (la selección es CARACTER11-1 por razones de espacio) (tecla mayus) + drawSelection(OFFSETX-2 + Xsel*CARACTER11, WRITTENSPACE + Ysel*CARACTER11, CARACTER11, CARACTER11-1, lcd); + } + }else{ + // Se borra la selección anterior + drawDeselection(OFFSETX-2 + Xsel*CARACTER11, WRITTENSPACE + Ysel*CARACTER11, CARACTER11, CARACTER11, lcd); + // Se selecciona el nuevo elemento + Xsel--; + // Se escribe la nueva selección + drawSelection(OFFSETX-2 + Xsel*CARACTER11, WRITTENSPACE + Ysel*CARACTER11, CARACTER11, CARACTER11, lcd); + } + // transmit work screen to physical screen: + lcd->Flush(); + } +} + +// El botón 3 desplaza la selección al elemento derecho al actual +void Teclado::button3pressed(DogMLCD* lcd){ + // Si sales de los elementos seleccionables no se cambia de selección + if((Xsel + 1) < COLUMNASMATRIZ){ + // Si se está en la última fila + if(Ysel == (FILASMATRIZ-1) ){ + // Se se venía de la tecla mayus + if(m[Ysel][Xsel] == MAYUS){ + drawDeselection(OFFSETX-2 + Xsel*CARACTER11, WRITTENSPACE + Ysel*CARACTER11, CARACTER11, CARACTER11-1, lcd); + seleccionarBarraEspaciadora(lcd); + // Se mueven un elemento a la derecha + Xsel++; + }else if(m[Ysel][Xsel] == SPACEBAR){ //si se venía de la barra espaciadora + deseleccionarBarraEspaciadora(lcd); + // Se mueve la selección al penultimo elemento + Xsel = 9; + // Se escribe la nueva selección (la selección es CARACTER11-1 por razones de espacio) (tecla mayus) + seleccionarAplicar(lcd); + } + }else{ + // Se borra la selección anterior + drawDeselection(OFFSETX-2 + Xsel*CARACTER11, WRITTENSPACE + Ysel*CARACTER11, CARACTER11, CARACTER11, lcd); + // Se selecciona el nuevo elemento + Xsel++; + // Se escribe la nueva selección + drawSelection(OFFSETX-2 + Xsel*CARACTER11, WRITTENSPACE + Ysel*CARACTER11, CARACTER11, CARACTER11, lcd); + } + + // transmit work screen to physical screen: + lcd->Flush(); + } +} + +// El botón 4 baja la selección al elemento superior al actual +void Teclado::button4pressed(DogMLCD* lcd){ + // Si sales de los elementos seleccionables no se cambia de selección + if((Ysel + 1) < FILASMATRIZ){ + // Se borra la selección anterior + drawDeselection(OFFSETX-2 + Xsel*CARACTER11, WRITTENSPACE + Ysel*CARACTER11, CARACTER11, CARACTER11, lcd); + // Se selecciona el nuevo elemento + Ysel++; + + // Si la siguiente fila es la última (teclas especiales) + if(Ysel == (FILASMATRIZ-1) ){ + // Se guarda la última tecla que estaba seleccionada + lastXsel = Xsel; + lastYsel = Ysel-1; + // Si se va hacia la barra espaciadora se selecciona esta + if(m[Ysel][Xsel] == SPACEBAR){ + seleccionarBarraEspaciadora(lcd); + }else if(m[Ysel][Xsel] == APLICAR){ // Si se va hacia la tecla aplicar se selecciona esta + seleccionarAplicar(lcd); + }else{ + // Se escribe la nueva selección (la selección es CARACTER11-1 por razones de espacio) (tecla mayus) + drawSelection(OFFSETX-2 + Xsel*CARACTER11, WRITTENSPACE + Ysel*CARACTER11, CARACTER11, CARACTER11-1, lcd); + } + }else{ + // Se escribe la nueva selección + drawSelection(OFFSETX-2 + Xsel*CARACTER11, WRITTENSPACE + Ysel*CARACTER11, CARACTER11, CARACTER11, lcd); + } + + // transmit work screen to physical screen: + lcd->Flush(); + } +} + +char *Teclado::getNombre(){ + return nombre; +} + +// Esta función guarda la pantalla a la que se debe volver en caso de ser pulsado el boton atras +void Teclado::setNextScreen(char nameScreen[NCARSCREEN]){ + strcpy(nameNextScreen, nameScreen); +} + +void Teclado::asignarMinusculas(){ + // Primera fila + m[0][0] = 'q'; + m[0][1] = 'w'; + m[0][2] = 'e'; + m[0][3] = 'r'; + m[0][4] = 't'; + m[0][5] = 'y'; + m[0][6] = 'u'; + m[0][7] = 'i'; + m[0][8] = 'o'; + m[0][9] = 'p'; + m[0][10] = '('; + + // Segunda fila + m[1][0] = 'a'; + m[1][1] = 's'; + m[1][2] = 'd'; + m[1][3] = 'f'; + m[1][4] = 'g'; + m[1][5] = 'h'; + m[1][6] = 'j'; + m[1][7] = 'k'; + m[1][8] = 'l'; + m[1][9] = 164; + m[1][10] = ')'; + + // Tercera fila + m[2][0] = 'z'; + m[2][1] = 'x'; + m[2][2] = 'c'; + m[2][3] = 'v'; + m[2][4] = 'b'; + m[2][5] = 'n'; + m[2][6] = 'm'; + m[2][7] = ','; + m[2][8] = '.'; + m[2][9] = ';'; + m[2][10] = '_'; + + // Cuarta fila + m[3][0] = '1'; + m[3][1] = '2'; + m[3][2] = '3'; + m[3][3] = '4'; + m[3][4] = '5'; + m[3][5] = '6'; + m[3][6] = '7'; + m[3][7] = '8'; + m[3][8] = '9'; + m[3][9] = '0'; + m[3][10] = BACK; + + // Quinta fila + m[4][0] = MAYUS; + m[4][1] = SPACEBAR; + m[4][2] = SPACEBAR; + m[4][3] = SPACEBAR; + m[4][4] = SPACEBAR; + m[4][5] = SPACEBAR; + m[4][6] = SPACEBAR; + m[4][7] = SPACEBAR; + m[4][8] = SPACEBAR; + m[4][9] = APLICAR; + m[4][10] = APLICAR; +} + +void Teclado::asignarMayusculas(){ + // Primera fila + m[0][0] = 'Q'; + m[0][1] = 'W'; + m[0][2] = 'E'; + m[0][3] = 'R'; + m[0][4] = 'T'; + m[0][5] = 'Y'; + m[0][6] = 'U'; + m[0][7] = 'I'; + m[0][8] = 'O'; + m[0][9] = 'P'; + m[0][10] = '('; + + // Segunda fila + m[1][0] = 'A'; + m[1][1] = 'S'; + m[1][2] = 'D'; + m[1][3] = 'F'; + m[1][4] = 'G'; + m[1][5] = 'H'; + m[1][6] = 'J'; + m[1][7] = 'K'; + m[1][8] = 'L'; + m[1][9] = 165; + m[1][10] = ')'; + + // Tercera fila + m[2][0] = 'Z'; + m[2][1] = 'X'; + m[2][2] = 'C'; + m[2][3] = 'V'; + m[2][4] = 'B'; + m[2][5] = 'N'; + m[2][6] = 'M'; + m[2][7] = ','; + m[2][8] = '.'; + m[2][9] = ';'; + m[2][10] = '_'; + + // Cuarta fila + m[3][0] = '1'; + m[3][1] = '2'; + m[3][2] = '3'; + m[3][3] = '4'; + m[3][4] = '5'; + m[3][5] = '6'; + m[3][6] = '7'; + m[3][7] = '8'; + m[3][8] = '9'; + m[3][9] = '0'; + m[3][10] = BACK; + + // Quinta fila + m[4][0] = MAYUS; + m[4][1] = SPACEBAR; + m[4][2] = SPACEBAR; + m[4][3] = SPACEBAR; + m[4][4] = SPACEBAR; + m[4][5] = SPACEBAR; + m[4][6] = SPACEBAR; + m[4][7] = SPACEBAR; + m[4][8] = SPACEBAR; + m[4][9] = APLICAR; + m[4][10] = APLICAR; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ScreenManager/Teclado.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,85 @@ +/** + * @author Juan Manuel Amador Olivares (virtualmech) + */ +#ifndef TECLADO_H +#define TECLADO_H + +#include "Seleccion.h" +#include "doggy.h" + +#define POSCADENAX 3 +#define OFFSETX 4 // Espacio en pixeles que se deja antes de escribir una linea de caracteres +#define OFFSETY 4 // Espacio en pixeles que se deja antes de escribir una linea de caracteres en la parte superior +#define CARACTER11 11 // Anchura de un caracter de media +#define CARACTER8 8 // Anchura de un caracter de media +#define WRITTENSPACE 9 // Pixeles de alto que requiere el espacio donde se irá mostrando lo que se está escribiendo con el teclado +#define MAXCARACTERESESCRITURA 19 // Máximos caracteres que se pueden escribir para el nombre del archivo + +#define FILASMATRIZ 5 +#define COLUMNASMATRIZ 11 + + +/*************************** + Para controlar la posición del teclado se va a hacer una matriz de 11x5. A cada elemento de la matriz se le asignará un valor (la letra correspondiente) + y valores especiales las teclas especiales: + + 0-> espacio vacio + 1-> borrar + 2-> mayus + 3-> barra espaciadora + 4-> Aplicar + **************************/ +#define BACK 1 +#define MAYUS 2 +#define SPACEBAR 3 +#define APLICAR 4 + +#define ULTIMOCARACTERESPECIAL 4 // Se va a usar para comprobar si un elemento de la matrzi es un caracter especial o tecla especial + + +// Lista de elementos seleccionables. Tamaño de caracteres 8. +class Teclado: public Seleccion{ + public: + + virtual void initialize(DogMLCD* lcd); + int addElement(char text[], char nameNextScreen[NCARSCREEN]); + + char *getNombre(); // Devuelve un puntero al último nombre escrito con el teclado + + void setNextScreen(char nameScreen[NCARSCREEN]); + + virtual void button1pressed(DogMLCD* lcd); // Esta función se llama cuando el botón superior es pulsado, definirla para añadir funcionalidades + virtual void button2pressed(DogMLCD* lcd); // Esta función se llama cuando el botón superior es pulsado, definirla para añadir funcionalidades + virtual void button3pressed(DogMLCD* lcd); // Esta función se llama cuando el botón superior es pulsado, definirla para añadir funcionalidades + virtual void button4pressed(DogMLCD* lcd); // Esta función se llama cuando el botón inferior es pulsado, definirla para añadir funcionalidades + virtual void button5pressed(DogMLCD* lcd); // Esta función se llama cuando el botón central es pulsado, definirla para añadir funcionalidades + + private: + + char nameNextScreen[NCARSCREEN]; + + char m[FILASMATRIZ][COLUMNASMATRIZ]; + char Xsel, Ysel, lastXsel, lastYsel; // posición x e y en la matriz del elemento seleccionado y el anterior + + char nombre[MAXCARACTERESESCRITURA+1]; // Guarda la cadena con el nombre escrito + char indiceEscritura; // Indica por donde se va escribiendo en el recuadro + + void mostrarCaracteres(DogMLCD* lcd); // Muestra los caracteres de la matriz + void mostrarEspeciales(DogMLCD* lcd); // Muestra los caracteres especiales + void asignarMinusculas(); // Asigna a la matriz valores de caracteres de las letras minusculas + void asignarMayusculas(); // Asigna a la matriz valores de caracteres de las letras minusculas + + void mostrarRecuadro(DogMLCD* lcd); // Muestra el recuadro que señala lo que se está escribiendo + + // Cuadros seleccionables especiales + void seleccionarBarraEspaciadora(DogMLCD* lcd); + void deseleccionarBarraEspaciadora(DogMLCD* lcd); + + void seleccionarAplicar(DogMLCD* lcd); + void deseleccionarAplicar(DogMLCD* lcd); + + bool ifMayus; + +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHostLite/usbhost_cpu.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,35 @@ +/* +************************************************************************************************************** +* NXP USB Host Stack +* +* (c) Copyright 2008, NXP SemiConductors +* (c) Copyright 2008, OnChip Technologies LLC +* All Rights Reserved +* +* www.nxp.com +* www.onchiptech.com +* +* File : usbhost_cpu.h +* Programmer(s) : Ravikanth.P +* Version : +* +************************************************************************************************************** +*/ + +#ifndef USBHOST_CPU_H +#define USBHOST_CPU_H + +/* +************************************************************************************************************** +* TYPE DEFINITIONS OF DATA TYPES +************************************************************************************************************** +*/ + +typedef unsigned int USB_INT32U; +typedef signed int USB_INT32S; +typedef unsigned short USB_INT16U; +typedef signed short USB_INT16S; +typedef unsigned char USB_INT08U; +typedef signed char USB_INT08S; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHostLite/usbhost_err.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,63 @@ +/* +************************************************************************************************************** +* NXP USB Host Stack +* +* (c) Copyright 2008, NXP SemiConductors +* (c) Copyright 2008, OnChip Technologies LLC +* All Rights Reserved +* +* www.nxp.com +* www.onchiptech.com +* +* File : usbhost_err.h +* Programmer(s) : Ravikanth.P +* Version : +* +************************************************************************************************************** +*/ + +#ifndef USBHOST_ERR_H +#define USBHOST_ERR_H + + +/* +************************************************************************************************************** +* GENERAL DEFINITIONS +************************************************************************************************************** +*/ + +#define OK 0 +#define MATCH_FOUND 0 + +/* +************************************************************************************************************** +* HOST CONTROLLER SPECIFIC ERROR CODES +************************************************************************************************************** +*/ + +#define ERR_TD_FAIL -1 + +/* +************************************************************************************************************** +* MASS STORAGE SPECIFIC ERROR CODES +************************************************************************************************************** +*/ + +#define ERR_MS_CMD_FAILED -10 +#define ERR_BAD_CONFIGURATION -11 +#define ERR_NO_MS_INTERFACE -12 + +/* +************************************************************************************************************** +* FAT SPECIFIC ERROR CODES +************************************************************************************************************** +*/ + +#define MATCH_NOT_FOUND -20 +#define ERR_FAT_NOT_SUPPORTED -21 +#define ERR_OPEN_LIMIT_REACHED -22 +#define ERR_INVALID_BOOT_SIG -23 +#define ERR_INVALID_BOOT_SEC -24 +#define ERR_ROOT_DIR_FULL -25 + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHostLite/usbhost_inc.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,39 @@ +/* +************************************************************************************************************** +* NXP USB Host Stack +* +* (c) Copyright 2008, NXP SemiConductors +* (c) Copyright 2008, OnChip Technologies LLC +* All Rights Reserved +* +* www.nxp.com +* www.onchiptech.com +* +* File : usbhost_inc.h +* Programmer(s) : Ravikanth.P +* Version : +* +************************************************************************************************************** +*/ + +#ifndef USBHOST_INC_H +#define USBHOST_INC_H + +/* +************************************************************************************************************** +* INCLUDE HEADER FILES +************************************************************************************************************** +*/ + +#include "usbhost_cpu.h" +#include "usbhost_err.h" +#include "usbhost_lpc17xx.h" +#include "usbhost_ms.h" +#include "mbed.h" + + +#ifdef TARGET_LPC2368 +#error "There is no USB host on the LPC2368!" +#endif + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHostLite/usbhost_lpc17xx.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,824 @@ +/* +************************************************************************************************************** +* NXP USB Host Stack +* +* (c) Copyright 2008, NXP SemiConductors +* (c) Copyright 2008, OnChip Technologies LLC +* All Rights Reserved +* +* www.nxp.com +* www.onchiptech.com +* +* File : usbhost_lpc17xx.c +* Programmer(s) : Ravikanth.P +* Version : +* +************************************************************************************************************** +*/ + +/* +************************************************************************************************************** +* INCLUDE HEADER FILES +************************************************************************************************************** +*/ +#include "mbed.h" +#include "usbhost_lpc17xx.h" + +extern DigitalOut myled; +extern Timer t; + +/* +************************************************************************************************************** +* GLOBAL VARIABLES +************************************************************************************************************** +*/ +int gUSBConnected; + +volatile USB_INT32U HOST_RhscIntr = 0; /* Root Hub Status Change interrupt */ +volatile USB_INT32U HOST_WdhIntr = 0; /* Semaphore to wait until the TD is submitted */ +volatile USB_INT08U HOST_TDControlStatus = 0; +volatile HCED *EDCtrl; /* Control endpoint descriptor structure */ +volatile HCED *EDBulkIn; /* BulkIn endpoint descriptor structure */ +volatile HCED *EDBulkOut; /* BulkOut endpoint descriptor structure */ +volatile HCTD *TDHead; /* Head transfer descriptor structure */ +volatile HCTD *TDTail; /* Tail transfer descriptor structure */ +volatile HCCA *Hcca; /* Host Controller Communications Area structure */ + USB_INT16U *TDBufNonVol; /* Identical to TDBuffer just to reduce compiler warnings */ +volatile USB_INT08U *TDBuffer; /* Current Buffer Pointer of transfer descriptor */ + +// USB host structures +// AHB SRAM block 1 +#define HOSTBASEADDR 0x2007C000 +// reserve memory for the linker +static USB_INT08U HostBuf[0x200] __attribute__((at(HOSTBASEADDR))); +/* +************************************************************************************************************** +* DELAY IN MILLI SECONDS +* +* Description: This function provides a delay in milli seconds +* +* Arguments : delay The delay required +* +* Returns : None +* +************************************************************************************************************** +*/ + +void Host_DelayMS (USB_INT32U delay) +{ + volatile USB_INT32U i; + + + for (i = 0; i < delay; i++) { + Host_DelayUS(1000); + } +} + +/* +************************************************************************************************************** +* DELAY IN MICRO SECONDS +* +* Description: This function provides a delay in micro seconds +* +* Arguments : delay The delay required +* +* Returns : None +* +************************************************************************************************************** +*/ + +void Host_DelayUS (USB_INT32U delay) +{ + volatile USB_INT32U i; + + + for (i = 0; i < (4 * delay); i++) { /* This logic was tested. It gives app. 1 micro sec delay */ + ; + } +} + +// bits of the USB/OTG clock control register +#define HOST_CLK_EN (1<<0) +#define DEV_CLK_EN (1<<1) +#define PORTSEL_CLK_EN (1<<3) +#define AHB_CLK_EN (1<<4) + +// bits of the USB/OTG clock status register +#define HOST_CLK_ON (1<<0) +#define DEV_CLK_ON (1<<1) +#define PORTSEL_CLK_ON (1<<3) +#define AHB_CLK_ON (1<<4) + +// we need host clock, OTG/portsel clock and AHB clock +#define CLOCK_MASK (HOST_CLK_EN | PORTSEL_CLK_EN | AHB_CLK_EN) + +/* +************************************************************************************************************** +* INITIALIZE THE HOST CONTROLLER +* +* Description: This function initializes lpc17xx host controller +* +* Arguments : None +* +* Returns : +* +************************************************************************************************************** +*/ +void Host_Init (void) +{ + PRINT_Log("In Host_Init\n"); + NVIC_DisableIRQ(USB_IRQn); /* Disable the USB interrupt source */ + + // turn on power for USB + LPC_SC->PCONP |= (1UL<<31); + // Enable USB host clock, port selection and AHB clock + LPC_USB->USBClkCtrl |= CLOCK_MASK; + // Wait for clocks to become available + while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK) + ; + + // it seems the bits[0:1] mean the following + // 0: U1=device, U2=host + // 1: U1=host, U2=host + // 2: reserved + // 3: U1=host, U2=device + // NB: this register is only available if OTG clock (aka "port select") is enabled!! + // since we don't care about port 2, set just bit 0 to 1 (U1=host) + LPC_USB->OTGStCtrl |= 1; + + // now that we've configured the ports, we can turn off the portsel clock + LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN; + + // power pins are not connected on mbed, so we can skip them + /* P1[18] = USB_UP_LED, 01 */ + /* P1[19] = /USB_PPWR, 10 */ + /* P1[22] = USB_PWRD, 10 */ + /* P1[27] = /USB_OVRCR, 10 */ + /*LPC_PINCON->PINSEL3 &= ~((3<<4) | (3<<6) | (3<<12) | (3<<22)); + LPC_PINCON->PINSEL3 |= ((1<<4)|(2<<6) | (2<<12) | (2<<22)); // 0x00802080 + */ + + // configure USB D+/D- pins + /* P0[29] = USB_D+, 01 */ + /* P0[30] = USB_D-, 01 */ + LPC_PINCON->PINSEL1 &= ~((3<<26) | (3<<28)); + LPC_PINCON->PINSEL1 |= ((1<<26)|(1<<28)); // 0x14000000 + + PRINT_Log("Initializing Host Stack\n"); + + Hcca = (volatile HCCA *)(HostBuf+0x000); + TDHead = (volatile HCTD *)(HostBuf+0x100); + TDTail = (volatile HCTD *)(HostBuf+0x110); + EDCtrl = (volatile HCED *)(HostBuf+0x120); + EDBulkIn = (volatile HCED *)(HostBuf+0x130); + EDBulkOut = (volatile HCED *)(HostBuf+0x140); + TDBuffer = (volatile USB_INT08U *)(HostBuf+0x150); + + /* Initialize all the TDs, EDs and HCCA to 0 */ + Host_EDInit(EDCtrl); + Host_EDInit(EDBulkIn); + Host_EDInit(EDBulkOut); + Host_TDInit(TDHead); + Host_TDInit(TDTail); + Host_HCCAInit(Hcca); + + Host_DelayMS(50); /* Wait 50 ms before apply reset */ + LPC_USB->HcControl = 0; /* HARDWARE RESET */ + LPC_USB->HcControlHeadED = 0; /* Initialize Control list head to Zero */ + LPC_USB->HcBulkHeadED = 0; /* Initialize Bulk list head to Zero */ + + /* SOFTWARE RESET */ + LPC_USB->HcCommandStatus = OR_CMD_STATUS_HCR; + LPC_USB->HcFmInterval = DEFAULT_FMINTERVAL; /* Write Fm Interval and Largest Data Packet Counter */ + + /* Put HC in operational state */ + LPC_USB->HcControl = (LPC_USB->HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER; + LPC_USB->HcRhStatus = OR_RH_STATUS_LPSC; /* Set Global Power */ + + LPC_USB->HcHCCA = (USB_INT32U)Hcca; + LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus; /* Clear Interrrupt Status */ + + + LPC_USB->HcInterruptEnable = OR_INTR_ENABLE_MIE | + OR_INTR_ENABLE_WDH | + OR_INTR_ENABLE_RHSC; + + NVIC_SetPriority(USB_IRQn, 0); /* highest priority */ + /* Enable the USB Interrupt */ + NVIC_EnableIRQ(USB_IRQn); + PRINT_Log("Host Initialized\n"); +} + +/* +************************************************************************************************************** +* INTERRUPT SERVICE ROUTINE +* +* Description: This function services the interrupt caused by host controller +* +* Arguments : None +* +* Returns : None +* +************************************************************************************************************** +*/ + +void USB_IRQHandler (void) __irq +{ + USB_INT32U int_status; + USB_INT32U ie_status; + + int_status = LPC_USB->HcInterruptStatus; /* Read Interrupt Status */ + ie_status = LPC_USB->HcInterruptEnable; /* Read Interrupt enable status */ + + if (!(int_status & ie_status)) { + return; + } else { + + int_status = int_status & ie_status; + if (int_status & OR_INTR_STATUS_RHSC) { /* Root hub status change interrupt */ + if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CSC) { + if (LPC_USB->HcRhStatus & OR_RH_STATUS_DRWE) { + /* + * When DRWE is on, Connect Status Change + * means a remote wakeup event. + */ + HOST_RhscIntr = 1;// JUST SOMETHING FOR A BREAKPOINT + } + else { + /* + * When DRWE is off, Connect Status Change + * is NOT a remote wakeup event + */ + if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CCS) { + if (!gUSBConnected) { + HOST_TDControlStatus = 0; + HOST_WdhIntr = 0; + HOST_RhscIntr = 1; + gUSBConnected = 1; + } + else + PRINT_Log("Spurious status change (connected)?\n"); + } else { + if (gUSBConnected) { + LPC_USB->HcInterruptEnable = 0; // why do we get multiple disc. rupts??? + HOST_RhscIntr = 0; + gUSBConnected = 0; + } + else + PRINT_Log("Spurious status change (disconnected)?\n"); + } + } + LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC; + } + if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRSC) { + LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC; + } + } + if (int_status & OR_INTR_STATUS_WDH) { /* Writeback Done Head interrupt */ + HOST_WdhIntr = 1; + HOST_TDControlStatus = (TDHead->Control >> 28) & 0xf; + } + LPC_USB->HcInterruptStatus = int_status; /* Clear interrupt status register */ + } + return; +} + +/* +************************************************************************************************************** +* PROCESS TRANSFER DESCRIPTOR +* +* Description: This function processes the transfer descriptor +* +* Arguments : ed Endpoint descriptor that contains this transfer descriptor +* token SETUP, IN, OUT +* buffer Current Buffer Pointer of the transfer descriptor +* buffer_len Length of the buffer +* +* Returns : OK if TD submission is successful +* ERROR if TD submission fails +* +************************************************************************************************************** +*/ + +USB_INT32S Host_ProcessTD (volatile HCED *ed, + volatile USB_INT32U token, + volatile USB_INT08U *buffer, + USB_INT32U buffer_len) +{ + volatile USB_INT32U td_toggle; + + + if (ed == EDCtrl) { + if (token == TD_SETUP) { + td_toggle = TD_TOGGLE_0; + } else { + td_toggle = TD_TOGGLE_1; + } + } else { + td_toggle = 0; + } + TDHead->Control = (TD_ROUNDING | + token | + TD_DELAY_INT(0) | + td_toggle | + TD_CC); + TDTail->Control = 0; + TDHead->CurrBufPtr = (USB_INT32U) buffer; + TDTail->CurrBufPtr = 0; + TDHead->Next = (USB_INT32U) TDTail; + TDTail->Next = 0; + TDHead->BufEnd = (USB_INT32U)(buffer + (buffer_len - 1)); + TDTail->BufEnd = 0; + + ed->HeadTd = (USB_INT32U)TDHead | ((ed->HeadTd) & 0x00000002); + ed->TailTd = (USB_INT32U)TDTail; + ed->Next = 0; + + if (ed == EDCtrl) { + LPC_USB->HcControlHeadED = (USB_INT32U)ed; + LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | OR_CMD_STATUS_CLF; + LPC_USB->HcControl = LPC_USB->HcControl | OR_CONTROL_CLE; + } else { + LPC_USB->HcBulkHeadED = (USB_INT32U)ed; + LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | OR_CMD_STATUS_BLF; + LPC_USB->HcControl = LPC_USB->HcControl | OR_CONTROL_BLE; + } + + Host_WDHWait(); + +// if (!(TDHead->Control & 0xF0000000)) { + if (!HOST_TDControlStatus) { + return (OK); + } else { + return (ERR_TD_FAIL); + } +} + +/* +************************************************************************************************************** +* ENUMERATE THE DEVICE +* +* Description: This function is used to enumerate the device connected +* +* Arguments : None +* +* Returns : None +* +************************************************************************************************************** +*/ + +USB_INT32S Host_EnumDev (void) +{ + USB_INT32S rc; + + PRINT_Log("Connect a Mass Storage device\n"); + while (!HOST_RhscIntr) + __WFI(); + myled = 1; + Host_DelayMS(100); /* USB 2.0 spec says atleast 50ms delay beore port reset */ + LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRS; // Initiate port reset + while (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRS) + __WFI(); // Wait for port reset to complete... + LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC; // ...and clear port reset signal + Host_DelayMS(200); /* Wait for 100 MS after port reset */ + + EDCtrl->Control = 8 << 16; /* Put max pkt size = 8 */ + /* Read first 8 bytes of device desc */ + rc = HOST_GET_DESCRIPTOR(USB_DESCRIPTOR_TYPE_DEVICE, 0, TDBuffer, 8); + if (rc != OK) { + PRINT_Err(rc); + return (rc); + } + EDCtrl->Control = TDBuffer[7] << 16; /* Get max pkt size of endpoint 0 */ + rc = HOST_SET_ADDRESS(1); /* Set the device address to 1 */ + if (rc != OK) { + PRINT_Err(rc); + return (rc); + } + Host_DelayMS(2); + EDCtrl->Control = (EDCtrl->Control) | 1; /* Modify control pipe with address 1 */ + /* Get the configuration descriptor */ + rc = HOST_GET_DESCRIPTOR(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, TDBuffer, 9); + if (rc != OK) { + PRINT_Err(rc); + return (rc); + } + /* Get the first configuration data */ + rc = HOST_GET_DESCRIPTOR(USB_DESCRIPTOR_TYPE_CONFIGURATION, 0, TDBuffer, ReadLE16U(&TDBuffer[2])); + if (rc != OK) { + PRINT_Err(rc); + return (rc); + } + rc = MS_ParseConfiguration(); /* Parse the configuration */ + if (rc != OK) { + PRINT_Err(rc); + return (rc); + } + rc = USBH_SET_CONFIGURATION(1); /* Select device configuration 1 */ + if (rc != OK) { + PRINT_Err(rc); + } + Host_DelayMS(100); /* Some devices may require this delay */ + return (rc); +} + +/* +************************************************************************************************************** +* RECEIVE THE CONTROL INFORMATION +* +* Description: This function is used to receive the control information +* +* Arguments : bm_request_type +* b_request +* w_value +* w_index +* w_length +* buffer +* +* Returns : OK if Success +* ERROR if Failed +* +************************************************************************************************************** +*/ + +USB_INT32S Host_CtrlRecv ( USB_INT08U bm_request_type, + USB_INT08U b_request, + USB_INT16U w_value, + USB_INT16U w_index, + USB_INT16U w_length, + volatile USB_INT08U *buffer) +{ + USB_INT32S rc; + + + Host_FillSetup(bm_request_type, b_request, w_value, w_index, w_length); + rc = Host_ProcessTD(EDCtrl, TD_SETUP, TDBuffer, 8); + if (rc == OK) { + if (w_length) { + rc = Host_ProcessTD(EDCtrl, TD_IN, TDBuffer, w_length); + } + if (rc == OK) { + rc = Host_ProcessTD(EDCtrl, TD_OUT, NULL, 0); + } + } + return (rc); +} + +/* +************************************************************************************************************** +* SEND THE CONTROL INFORMATION +* +* Description: This function is used to send the control information +* +* Arguments : None +* +* Returns : OK if Success +* ERR_INVALID_BOOTSIG if Failed +* +************************************************************************************************************** +*/ + +USB_INT32S Host_CtrlSend ( USB_INT08U bm_request_type, + USB_INT08U b_request, + USB_INT16U w_value, + USB_INT16U w_index, + USB_INT16U w_length, + volatile USB_INT08U *buffer) +{ + USB_INT32S rc; + + + Host_FillSetup(bm_request_type, b_request, w_value, w_index, w_length); + + rc = Host_ProcessTD(EDCtrl, TD_SETUP, TDBuffer, 8); + if (rc == OK) { + if (w_length) { + rc = Host_ProcessTD(EDCtrl, TD_OUT, TDBuffer, w_length); + } + if (rc == OK) { + rc = Host_ProcessTD(EDCtrl, TD_IN, NULL, 0); + } + } + return (rc); +} + +/* +************************************************************************************************************** +* FILL SETUP PACKET +* +* Description: This function is used to fill the setup packet +* +* Arguments : None +* +* Returns : OK if Success +* ERR_INVALID_BOOTSIG if Failed +* +************************************************************************************************************** +*/ + +void Host_FillSetup (USB_INT08U bm_request_type, + USB_INT08U b_request, + USB_INT16U w_value, + USB_INT16U w_index, + USB_INT16U w_length) +{ + int i; + for (i=0;i<w_length;i++) + TDBuffer[i] = 0; + + TDBuffer[0] = bm_request_type; + TDBuffer[1] = b_request; + WriteLE16U(&TDBuffer[2], w_value); + WriteLE16U(&TDBuffer[4], w_index); + WriteLE16U(&TDBuffer[6], w_length); +} + + + +/* +************************************************************************************************************** +* INITIALIZE THE TRANSFER DESCRIPTOR +* +* Description: This function initializes transfer descriptor +* +* Arguments : Pointer to TD structure +* +* Returns : None +* +************************************************************************************************************** +*/ + +void Host_TDInit (volatile HCTD *td) +{ + + td->Control = 0; + td->CurrBufPtr = 0; + td->Next = 0; + td->BufEnd = 0; +} + +/* +************************************************************************************************************** +* INITIALIZE THE ENDPOINT DESCRIPTOR +* +* Description: This function initializes endpoint descriptor +* +* Arguments : Pointer to ED strcuture +* +* Returns : None +* +************************************************************************************************************** +*/ + +void Host_EDInit (volatile HCED *ed) +{ + + ed->Control = 0; + ed->TailTd = 0; + ed->HeadTd = 0; + ed->Next = 0; +} + +/* +************************************************************************************************************** +* INITIALIZE HOST CONTROLLER COMMUNICATIONS AREA +* +* Description: This function initializes host controller communications area +* +* Arguments : Pointer to HCCA +* +* Returns : +* +************************************************************************************************************** +*/ + +void Host_HCCAInit (volatile HCCA *hcca) +{ + USB_INT32U i; + + + for (i = 0; i < 32; i++) { + + hcca->IntTable[i] = 0; + hcca->FrameNumber = 0; + hcca->DoneHead = 0; + } + +} + +/* +************************************************************************************************************** +* WAIT FOR WDH INTERRUPT +* +* Description: This function is infinite loop which breaks when ever a WDH interrupt rises +* +* Arguments : None +* +* Returns : None +* +************************************************************************************************************** +*/ + +void Host_WDHWait (void) +{ + while (!HOST_WdhIntr) + __WFI(); + + HOST_WdhIntr = 0; +} + +/* +************************************************************************************************************** +* READ LE 32U +* +* Description: This function is used to read an unsigned integer from a character buffer in the platform +* containing little endian processor +* +* Arguments : pmem Pointer to the character buffer +* +* Returns : val Unsigned integer +* +************************************************************************************************************** +*/ + +USB_INT32U ReadLE32U (volatile USB_INT08U *pmem) +{ + USB_INT32U val = *(USB_INT32U*)pmem; +#ifdef __BIG_ENDIAN + return __REV(val); +#else + return val; +#endif +} + +/* +************************************************************************************************************** +* WRITE LE 32U +* +* Description: This function is used to write an unsigned integer into a charecter buffer in the platform +* containing little endian processor. +* +* Arguments : pmem Pointer to the charecter buffer +* val Integer value to be placed in the charecter buffer +* +* Returns : None +* +************************************************************************************************************** +*/ + +void WriteLE32U (volatile USB_INT08U *pmem, + USB_INT32U val) +{ +#ifdef __BIG_ENDIAN + *(USB_INT32U*)pmem = __REV(val); +#else + *(USB_INT32U*)pmem = val; +#endif +} + +/* +************************************************************************************************************** +* READ LE 16U +* +* Description: This function is used to read an unsigned short integer from a charecter buffer in the platform +* containing little endian processor +* +* Arguments : pmem Pointer to the charecter buffer +* +* Returns : val Unsigned short integer +* +************************************************************************************************************** +*/ + +USB_INT16U ReadLE16U (volatile USB_INT08U *pmem) +{ + USB_INT16U val = *(USB_INT16U*)pmem; +#ifdef __BIG_ENDIAN + return __REV16(val); +#else + return val; +#endif +} + +/* +************************************************************************************************************** +* WRITE LE 16U +* +* Description: This function is used to write an unsigned short integer into a charecter buffer in the +* platform containing little endian processor +* +* Arguments : pmem Pointer to the charecter buffer +* val Value to be placed in the charecter buffer +* +* Returns : None +* +************************************************************************************************************** +*/ + +void WriteLE16U (volatile USB_INT08U *pmem, + USB_INT16U val) +{ +#ifdef __BIG_ENDIAN + *(USB_INT16U*)pmem = (__REV16(val) & 0xFFFF); +#else + *(USB_INT16U*)pmem = val; +#endif +} + +/* +************************************************************************************************************** +* READ BE 32U +* +* Description: This function is used to read an unsigned integer from a charecter buffer in the platform +* containing big endian processor +* +* Arguments : pmem Pointer to the charecter buffer +* +* Returns : val Unsigned integer +* +************************************************************************************************************** +*/ + +USB_INT32U ReadBE32U (volatile USB_INT08U *pmem) +{ + USB_INT32U val = *(USB_INT32U*)pmem; +#ifdef __BIG_ENDIAN + return val; +#else + return __REV(val); +#endif +} + +/* +************************************************************************************************************** +* WRITE BE 32U +* +* Description: This function is used to write an unsigned integer into a charecter buffer in the platform +* containing big endian processor +* +* Arguments : pmem Pointer to the charecter buffer +* val Value to be placed in the charecter buffer +* +* Returns : None +* +************************************************************************************************************** +*/ + +void WriteBE32U (volatile USB_INT08U *pmem, + USB_INT32U val) +{ +#ifdef __BIG_ENDIAN + *(USB_INT32U*)pmem = val; +#else + *(USB_INT32U*)pmem = __REV(val); +#endif +} + +/* +************************************************************************************************************** +* READ BE 16U +* +* Description: This function is used to read an unsigned short integer from a charecter buffer in the platform +* containing big endian processor +* +* Arguments : pmem Pointer to the charecter buffer +* +* Returns : val Unsigned short integer +* +************************************************************************************************************** +*/ + +USB_INT16U ReadBE16U (volatile USB_INT08U *pmem) +{ + USB_INT16U val = *(USB_INT16U*)pmem; +#ifdef __BIG_ENDIAN + return val; +#else + return __REV16(val); +#endif +} + +/* +************************************************************************************************************** +* WRITE BE 16U +* +* Description: This function is used to write an unsigned short integer into the charecter buffer in the +* platform containing big endian processor +* +* Arguments : pmem Pointer to the charecter buffer +* val Value to be placed in the charecter buffer +* +* Returns : None +* +************************************************************************************************************** +*/ + +void WriteBE16U (volatile USB_INT08U *pmem, + USB_INT16U val) +{ +#ifdef __BIG_ENDIAN + *(USB_INT16U*)pmem = val; +#else + *(USB_INT16U*)pmem = (__REV16(val) & 0xFFFF); +#endif +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHostLite/usbhost_lpc17xx.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,254 @@ +/* +************************************************************************************************************** +* NXP USB Host Stack +* +* (c) Copyright 2008, NXP SemiConductors +* (c) Copyright 2008, OnChip Technologies LLC +* All Rights Reserved +* +* www.nxp.com +* www.onchiptech.com +* +* File : usbhost_lpc17xx.h +* Programmer(s) : Ravikanth.P +* Version : +* +************************************************************************************************************** +*/ + +#ifndef USBHOST_LPC17xx_H +#define USBHOST_LPC17xx_H + +/* +************************************************************************************************************** +* INCLUDE HEADER FILES +************************************************************************************************************** +*/ + +#include "usbhost_inc.h" + +/* +************************************************************************************************************** +* PRINT CONFIGURATION +************************************************************************************************************** +*/ + +#define PRINT_ENABLE 1 + +#if PRINT_ENABLE +#define PRINT_Log(...) printf(__VA_ARGS__) +#define PRINT_Err(rc) printf("ERROR: In %s at Line %u - rc = %d\n", __FUNCTION__, __LINE__, rc) + +#else +#define PRINT_Log(...) do {} while(0) +#define PRINT_Err(rc) do {} while(0) + +#endif + +/* +************************************************************************************************************** +* GENERAL DEFINITIONS +************************************************************************************************************** +*/ + +#define DESC_LENGTH(x) x[0] +#define DESC_TYPE(x) x[1] + + +#define HOST_GET_DESCRIPTOR(descType, descIndex, data, length) \ + Host_CtrlRecv(USB_DEVICE_TO_HOST | USB_RECIPIENT_DEVICE, GET_DESCRIPTOR, \ + (descType << 8)|(descIndex), 0, length, data) + +#define HOST_SET_ADDRESS(new_addr) \ + Host_CtrlSend(USB_HOST_TO_DEVICE | USB_RECIPIENT_DEVICE, SET_ADDRESS, \ + new_addr, 0, 0, NULL) + +#define USBH_SET_CONFIGURATION(configNum) \ + Host_CtrlSend(USB_HOST_TO_DEVICE | USB_RECIPIENT_DEVICE, SET_CONFIGURATION, \ + configNum, 0, 0, NULL) + +#define USBH_SET_INTERFACE(ifNum, altNum) \ + Host_CtrlSend(USB_HOST_TO_DEVICE | USB_RECIPIENT_INTERFACE, SET_INTERFACE, \ + altNum, ifNum, 0, NULL) + +/* +************************************************************************************************************** +* OHCI OPERATIONAL REGISTER FIELD DEFINITIONS +************************************************************************************************************** +*/ + + /* ------------------ HcControl Register --------------------- */ +#define OR_CONTROL_CLE 0x00000010 +#define OR_CONTROL_BLE 0x00000020 +#define OR_CONTROL_HCFS 0x000000C0 +#define OR_CONTROL_HC_OPER 0x00000080 + /* ----------------- HcCommandStatus Register ----------------- */ +#define OR_CMD_STATUS_HCR 0x00000001 +#define OR_CMD_STATUS_CLF 0x00000002 +#define OR_CMD_STATUS_BLF 0x00000004 + /* --------------- HcInterruptStatus Register ----------------- */ +#define OR_INTR_STATUS_WDH 0x00000002 +#define OR_INTR_STATUS_RHSC 0x00000040 + /* --------------- HcInterruptEnable Register ----------------- */ +#define OR_INTR_ENABLE_WDH 0x00000002 +#define OR_INTR_ENABLE_RHSC 0x00000040 +#define OR_INTR_ENABLE_MIE 0x80000000 + /* ---------------- HcRhDescriptorA Register ------------------ */ +#define OR_RH_STATUS_LPSC 0x00010000 +#define OR_RH_STATUS_DRWE 0x00008000 + /* -------------- HcRhPortStatus[1:NDP] Register -------------- */ +#define OR_RH_PORT_CCS 0x00000001 +#define OR_RH_PORT_PRS 0x00000010 +#define OR_RH_PORT_CSC 0x00010000 +#define OR_RH_PORT_PRSC 0x00100000 + + +/* +************************************************************************************************************** +* FRAME INTERVAL +************************************************************************************************************** +*/ + +#define FI 0x2EDF /* 12000 bits per frame (-1) */ +#define DEFAULT_FMINTERVAL ((((6 * (FI - 210)) / 7) << 16) | FI) + +/* +************************************************************************************************************** +* TRANSFER DESCRIPTOR CONTROL FIELDS +************************************************************************************************************** +*/ + +#define TD_ROUNDING (USB_INT32U) (0x00040000) /* Buffer Rounding */ +#define TD_SETUP (USB_INT32U)(0) /* Direction of Setup Packet */ +#define TD_IN (USB_INT32U)(0x00100000) /* Direction In */ +#define TD_OUT (USB_INT32U)(0x00080000) /* Direction Out */ +#define TD_DELAY_INT(x) (USB_INT32U)((x) << 21) /* Delay Interrupt */ +#define TD_TOGGLE_0 (USB_INT32U)(0x02000000) /* Toggle 0 */ +#define TD_TOGGLE_1 (USB_INT32U)(0x03000000) /* Toggle 1 */ +#define TD_CC (USB_INT32U)(0xF0000000) /* Completion Code */ + +/* +************************************************************************************************************** +* USB STANDARD REQUEST DEFINITIONS +************************************************************************************************************** +*/ + +#define USB_DESCRIPTOR_TYPE_DEVICE 1 +#define USB_DESCRIPTOR_TYPE_CONFIGURATION 2 +#define USB_DESCRIPTOR_TYPE_INTERFACE 4 +#define USB_DESCRIPTOR_TYPE_ENDPOINT 5 + /* ----------- Control RequestType Fields ----------- */ +#define USB_DEVICE_TO_HOST 0x80 +#define USB_HOST_TO_DEVICE 0x00 +#define USB_REQUEST_TYPE_CLASS 0x20 +#define USB_RECIPIENT_DEVICE 0x00 +#define USB_RECIPIENT_INTERFACE 0x01 + /* -------------- USB Standard Requests -------------- */ +#define SET_ADDRESS 5 +#define GET_DESCRIPTOR 6 +#define SET_CONFIGURATION 9 +#define SET_INTERFACE 11 + +/* +************************************************************************************************************** +* TYPE DEFINITIONS +************************************************************************************************************** +*/ + +typedef struct hcEd { /* ----------- HostController EndPoint Descriptor ------------- */ + volatile USB_INT32U Control; /* Endpoint descriptor control */ + volatile USB_INT32U TailTd; /* Physical address of tail in Transfer descriptor list */ + volatile USB_INT32U HeadTd; /* Physcial address of head in Transfer descriptor list */ + volatile USB_INT32U Next; /* Physical address of next Endpoint descriptor */ +} HCED; + +typedef struct hcTd { /* ------------ HostController Transfer Descriptor ------------ */ + volatile USB_INT32U Control; /* Transfer descriptor control */ + volatile USB_INT32U CurrBufPtr; /* Physical address of current buffer pointer */ + volatile USB_INT32U Next; /* Physical pointer to next Transfer Descriptor */ + volatile USB_INT32U BufEnd; /* Physical address of end of buffer */ +} HCTD; + +typedef struct hcca { /* ----------- Host Controller Communication Area ------------ */ + volatile USB_INT32U IntTable[32]; /* Interrupt Table */ + volatile USB_INT32U FrameNumber; /* Frame Number */ + volatile USB_INT32U DoneHead; /* Done Head */ + volatile USB_INT08U Reserved[116]; /* Reserved for future use */ + volatile USB_INT08U Unknown[4]; /* Unused */ +} HCCA; + +/* +************************************************************************************************************** +* EXTERN DECLARATIONS +************************************************************************************************************** +*/ + +extern volatile HCED *EDBulkIn; /* BulkIn endpoint descriptor structure */ +extern volatile HCED *EDBulkOut; /* BulkOut endpoint descriptor structure */ +extern volatile HCTD *TDHead; /* Head transfer descriptor structure */ +extern volatile HCTD *TDTail; /* Tail transfer descriptor structure */ +extern volatile USB_INT08U *TDBuffer; /* Current Buffer Pointer of transfer descriptor */ + +/* +************************************************************************************************************** +* FUNCTION PROTOTYPES +************************************************************************************************************** +*/ + +void Host_Init (void); + +extern "C" void USB_IRQHandler(void) __irq; + +USB_INT32S Host_EnumDev (void); + +USB_INT32S Host_ProcessTD(volatile HCED *ed, + volatile USB_INT32U token, + volatile USB_INT08U *buffer, + USB_INT32U buffer_len); + +void Host_DelayUS ( USB_INT32U delay); +void Host_DelayMS ( USB_INT32U delay); + + +void Host_TDInit (volatile HCTD *td); +void Host_EDInit (volatile HCED *ed); +void Host_HCCAInit (volatile HCCA *hcca); + +USB_INT32S Host_CtrlRecv ( USB_INT08U bm_request_type, + USB_INT08U b_request, + USB_INT16U w_value, + USB_INT16U w_index, + USB_INT16U w_length, + volatile USB_INT08U *buffer); + +USB_INT32S Host_CtrlSend ( USB_INT08U bm_request_type, + USB_INT08U b_request, + USB_INT16U w_value, + USB_INT16U w_index, + USB_INT16U w_length, + volatile USB_INT08U *buffer); + +void Host_FillSetup( USB_INT08U bm_request_type, + USB_INT08U b_request, + USB_INT16U w_value, + USB_INT16U w_index, + USB_INT16U w_length); + + +void Host_WDHWait (void); + + +USB_INT32U ReadLE32U (volatile USB_INT08U *pmem); +void WriteLE32U (volatile USB_INT08U *pmem, + USB_INT32U val); +USB_INT16U ReadLE16U (volatile USB_INT08U *pmem); +void WriteLE16U (volatile USB_INT08U *pmem, + USB_INT16U val); +USB_INT32U ReadBE32U (volatile USB_INT08U *pmem); +void WriteBE32U (volatile USB_INT08U *pmem, + USB_INT32U val); +USB_INT16U ReadBE16U (volatile USB_INT08U *pmem); +void WriteBE16U (volatile USB_INT08U *pmem, + USB_INT16U val); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHostLite/usbhost_ms.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,455 @@ +/* +************************************************************************************************************** +* NXP USB Host Stack +* +* (c) Copyright 2008, NXP SemiConductors +* (c) Copyright 2008, OnChip Technologies LLC +* All Rights Reserved +* +* www.nxp.com +* www.onchiptech.com +* +* File : usbhost_ms.c +* Programmer(s) : Ravikanth.P +* Version : +* +************************************************************************************************************** +*/ + +/* +************************************************************************************************************** +* INCLUDE HEADER FILES +************************************************************************************************************** +*/ + +#include "usbhost_ms.h" + +/* +************************************************************************************************************** +* GLOBAL VARIABLES +************************************************************************************************************** +*/ + +USB_INT32U MS_BlkSize; + +/* +************************************************************************************************************** +* INITIALIZE MASS STORAGE INTERFACE +* +* Description: This function initializes the mass storage interface +* +* Arguments : None +* +* Returns : OK if Success +* ERR_INVALID_BOOTSIG if Failed +* +************************************************************************************************************** +*/ + +USB_INT32S MS_Init (USB_INT32U *blkSize, USB_INT32U *numBlks, USB_INT08U *inquiryResult) +{ + USB_INT08U retry; + USB_INT32S rc; + + MS_GetMaxLUN(); /* Get maximum logical unit number */ + retry = 80; + while(retry) { + rc = MS_TestUnitReady(); /* Test whether the unit is ready */ + if (rc == OK) { + break; + } + MS_GetSenseInfo(); /* Get sense information */ + retry--; + } + if (rc != OK) { + PRINT_Err(rc); + return (rc); + } + rc = MS_ReadCapacity(numBlks, blkSize); /* Read capacity of the disk */ + MS_BlkSize = *blkSize; // Set global + rc = MS_Inquire (inquiryResult); + return (rc); +} +/* +************************************************************************************************************** +* PARSE THE CONFIGURATION +* +* Description: This function is used to parse the configuration +* +* Arguments : None +* +* Returns : OK if Success +* ERR_INVALID_BOOTSIG if Failed +* +************************************************************************************************************** +*/ + +USB_INT32S MS_ParseConfiguration (void) +{ + volatile USB_INT08U *desc_ptr; + USB_INT08U ms_int_found; + + + desc_ptr = TDBuffer; + ms_int_found = 0; + + if (desc_ptr[1] != USB_DESCRIPTOR_TYPE_CONFIGURATION) { + return (ERR_BAD_CONFIGURATION); + } + desc_ptr += desc_ptr[0]; + + while (desc_ptr != TDBuffer + ReadLE16U(&TDBuffer[2])) { + + switch (desc_ptr[1]) { + + case USB_DESCRIPTOR_TYPE_INTERFACE: /* If it is an interface descriptor */ + if (desc_ptr[5] == MASS_STORAGE_CLASS && /* check if the class is mass storage */ + desc_ptr[6] == MASS_STORAGE_SUBCLASS_SCSI && /* check if the subclass is SCSI */ + desc_ptr[7] == MASS_STORAGE_PROTOCOL_BO) { /* check if the protocol is Bulk only */ + ms_int_found = 1; + desc_ptr += desc_ptr[0]; /* Move to next descriptor start */ + } + break; + + case USB_DESCRIPTOR_TYPE_ENDPOINT: /* If it is an endpoint descriptor */ + if ((desc_ptr[3] & 0x03) == 0x02) { /* If it is Bulk endpoint */ + if (desc_ptr[2] & 0x80) { /* If it is In endpoint */ + EDBulkIn->Control = 1 | /* USB address */ + ((desc_ptr[2] & 0x7F) << 7) | /* Endpoint address */ + (2 << 11) | /* direction */ + (ReadLE16U(&desc_ptr[4]) << 16); /* MaxPkt Size */ + desc_ptr += desc_ptr[0]; /* Move to next descriptor start */ + } else { /* If it is Out endpoint */ + EDBulkOut->Control = 1 | /* USB address */ + ((desc_ptr[2] & 0x7F) << 7) | /* Endpoint address */ + (1 << 11) | /* direction */ + (ReadLE16U(&desc_ptr[4]) << 16); /* MaxPkt Size */ + desc_ptr += desc_ptr[0]; /* Move to next descriptor start */ + } + } else { /* If it is not bulk end point */ + desc_ptr += desc_ptr[0]; /* Move to next descriptor start */ + } + break; + + default: /* If the descriptor is neither interface nor endpoint */ + desc_ptr += desc_ptr[0]; /* Move to next descriptor start */ + break; + } + } + if (ms_int_found) { + PRINT_Log("Mass Storage device connected\n"); + return (OK); + } else { + PRINT_Log("Not a Mass Storage device\n"); + return (ERR_NO_MS_INTERFACE); + } +} + +/* +************************************************************************************************************** +* GET MAXIMUM LOGICAL UNIT +* +* Description: This function returns the maximum logical unit from the device +* +* Arguments : None +* +* Returns : OK if Success +* ERR_INVALID_BOOTSIG if Failed +* +************************************************************************************************************** +*/ + +USB_INT32S MS_GetMaxLUN (void) +{ + USB_INT32S rc; + + + rc = Host_CtrlRecv(USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE, + MS_GET_MAX_LUN_REQ, + 0, + 0, + 1, + TDBuffer); + return (rc); +} + +/* +************************************************************************************************************** +* GET SENSE INFORMATION +* +* Description: This function is used to get sense information from the device +* +* Arguments : None +* +* Returns : OK if Success +* ERROR if Failed +* +************************************************************************************************************** +*/ + +USB_INT32S MS_GetSenseInfo (void) +{ + USB_INT32S rc; + + + Fill_MSCommand(0, 0, 0, MS_DATA_DIR_IN, SCSI_CMD_REQUEST_SENSE, 6); + rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE); + if (rc == OK) { + rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, 18); + if (rc == OK) { + rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE); + if (rc == OK) { + if (TDBuffer[12] != 0) { + rc = ERR_MS_CMD_FAILED; + } + } + } + } + return (rc); +} + +/* +************************************************************************************************************** +* TEST UNIT READY +* +* Description: This function is used to test whether the unit is ready or not +* +* Arguments : None +* +* Returns : OK if Success +* ERROR if Failed +* +************************************************************************************************************** +*/ + +USB_INT32S MS_TestUnitReady (void) +{ + USB_INT32S rc; + + + Fill_MSCommand(0, 0, 0, MS_DATA_DIR_NONE, SCSI_CMD_TEST_UNIT_READY, 6); + rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE); + if (rc == OK) { + rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE); + if (rc == OK) { + if (TDBuffer[12] != 0) { + rc = ERR_MS_CMD_FAILED; + } + } + } + return (rc); +} + +/* +************************************************************************************************************** +* READ CAPACITY +* +* Description: This function is used to read the capacity of the mass storage device +* +* Arguments : None +* +* Returns : OK if Success +* ERROR if Failed +* +************************************************************************************************************** +*/ + +USB_INT32S MS_ReadCapacity (USB_INT32U *numBlks, USB_INT32U *blkSize) +{ + USB_INT32S rc; + + + Fill_MSCommand(0, 0, 0, MS_DATA_DIR_IN, SCSI_CMD_READ_CAPACITY, 10); + rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE); + if (rc == OK) { + rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, 8); + if (rc == OK) { + if (numBlks) + *numBlks = ReadBE32U(&TDBuffer[0]); + if (blkSize) + *blkSize = ReadBE32U(&TDBuffer[4]); + rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE); + if (rc == OK) { + if (TDBuffer[12] != 0) { + rc = ERR_MS_CMD_FAILED; + } + } + } + } + return (rc); +} + + + +USB_INT32S MS_Inquire (USB_INT08U *response) +{ + USB_INT32S rc; + USB_INT32U i; + + Fill_MSCommand(0, 0, 0, MS_DATA_DIR_IN, SCSI_CMD_INQUIRY, 6); + rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE); + if (rc == OK) { + rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, INQUIRY_LENGTH); + if (rc == OK) { + if (response) { + for ( i = 0; i < INQUIRY_LENGTH; i++ ) + *response++ = *TDBuffer++; +#if 0 + MemCpy (response, TDBuffer, INQUIRY_LENGTH); + StrNullTrailingSpace (response->vendorID, SCSI_INQUIRY_VENDORCHARS); + StrNullTrailingSpace (response->productID, SCSI_INQUIRY_PRODUCTCHARS); + StrNullTrailingSpace (response->productRev, SCSI_INQUIRY_REVCHARS); +#endif + } + rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE); + if (rc == OK) { + if (TDBuffer[12] != 0) { // bCSWStatus byte + rc = ERR_MS_CMD_FAILED; + } + } + } + } + return (rc); +} + +/* +************************************************************************************************************** +* RECEIVE THE BULK DATA +* +* Description: This function is used to receive the bulk data +* +* Arguments : None +* +* Returns : OK if Success +* ERR_INVALID_BOOTSIG if Failed +* +************************************************************************************************************** +*/ + +USB_INT32S MS_BulkRecv ( USB_INT32U block_number, + USB_INT16U num_blocks, + volatile USB_INT08U *user_buffer) +{ + USB_INT32S rc; + int i; + volatile USB_INT08U *c = user_buffer; + for (i=0;i<MS_BlkSize*num_blocks;i++) + *c++ = 0; + + + Fill_MSCommand(block_number, MS_BlkSize, num_blocks, MS_DATA_DIR_IN, SCSI_CMD_READ_10, 10); + + rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE); + if (rc == OK) { + rc = Host_ProcessTD(EDBulkIn, TD_IN, user_buffer, MS_BlkSize * num_blocks); + if (rc == OK) { + rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE); + if (rc == OK) { + if (TDBuffer[12] != 0) { + rc = ERR_MS_CMD_FAILED; + } + } + } + } + return (rc); +} + +/* +************************************************************************************************************** +* SEND BULK DATA +* +* Description: This function is used to send the bulk data +* +* Arguments : None +* +* Returns : OK if Success +* ERR_INVALID_BOOTSIG if Failed +* +************************************************************************************************************** +*/ + +USB_INT32S MS_BulkSend ( USB_INT32U block_number, + USB_INT16U num_blocks, + volatile USB_INT08U *user_buffer) +{ + USB_INT32S rc; + + + Fill_MSCommand(block_number, MS_BlkSize, num_blocks, MS_DATA_DIR_OUT, SCSI_CMD_WRITE_10, 10); + + rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE); + if (rc == OK) { + rc = Host_ProcessTD(EDBulkOut, TD_OUT, user_buffer, MS_BlkSize * num_blocks); + if (rc == OK) { + rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE); + if (rc == OK) { + if (TDBuffer[12] != 0) { + rc = ERR_MS_CMD_FAILED; + } + } + } + } + return (rc); +} + +/* +************************************************************************************************************** +* FILL MASS STORAGE COMMAND +* +* Description: This function is used to fill the mass storage command +* +* Arguments : None +* +* Returns : OK if Success +* ERR_INVALID_BOOTSIG if Failed +* +************************************************************************************************************** +*/ + +void Fill_MSCommand (USB_INT32U block_number, + USB_INT32U block_size, + USB_INT16U num_blocks, + MS_DATA_DIR direction, + USB_INT08U scsi_cmd, + USB_INT08U scsi_cmd_len) +{ + USB_INT32U data_len; + static USB_INT32U tag_cnt = 0; + USB_INT32U cnt; + + + for (cnt = 0; cnt < CBW_SIZE; cnt++) { + TDBuffer[cnt] = 0; + } + switch(scsi_cmd) { + + case SCSI_CMD_TEST_UNIT_READY: + data_len = 0; + break; + case SCSI_CMD_READ_CAPACITY: + data_len = 8; + break; + case SCSI_CMD_REQUEST_SENSE: + data_len = 18; + break; + case SCSI_CMD_INQUIRY: + data_len = 36; + break; + default: + data_len = block_size * num_blocks; + break; + } + WriteLE32U(TDBuffer, CBW_SIGNATURE); + WriteLE32U(&TDBuffer[4], tag_cnt); + WriteLE32U(&TDBuffer[8], data_len); + TDBuffer[12] = (direction == MS_DATA_DIR_NONE) ? 0 : direction; + TDBuffer[14] = scsi_cmd_len; /* Length of the CBW */ + TDBuffer[15] = scsi_cmd; + if ((scsi_cmd == SCSI_CMD_REQUEST_SENSE) + || (scsi_cmd == SCSI_CMD_INQUIRY)) { + TDBuffer[19] = (USB_INT08U)data_len; + } else { + WriteBE32U(&TDBuffer[17], block_number); + } + WriteBE16U(&TDBuffer[22], num_blocks); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHostLite/usbhost_ms.h Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,101 @@ +/* +************************************************************************************************************** +* NXP USB Host Stack +* +* (c) Copyright 2008, NXP SemiConductors +* (c) Copyright 2008, OnChip Technologies LLC +* All Rights Reserved +* +* www.nxp.com +* www.onchiptech.com +* +* File : usbhost_ms.h +* Programmer(s) : Ravikanth.P +* Version : +* +************************************************************************************************************** +*/ + +#ifndef USBHOST_MS_H +#define USBHOST_MS_H + +/* +************************************************************************************************************** +* INCLUDE HEADER FILES +************************************************************************************************************** +*/ + +#include "usbhost_inc.h" + +/* +************************************************************************************************************** +* MASS STORAGE SPECIFIC DEFINITIONS +************************************************************************************************************** +*/ + +#define MS_GET_MAX_LUN_REQ 0xFE +#define MASS_STORAGE_CLASS 0x08 +#define MASS_STORAGE_SUBCLASS_SCSI 0x06 +#define MASS_STORAGE_PROTOCOL_BO 0x50 + +#define INQUIRY_LENGTH 36 +/* +************************************************************************************************************** +* SCSI SPECIFIC DEFINITIONS +************************************************************************************************************** +*/ + +#define CBW_SIGNATURE 0x43425355 +#define CSW_SIGNATURE 0x53425355 +#define CBW_SIZE 31 +#define CSW_SIZE 13 +#define CSW_CMD_PASSED 0x00 +#define SCSI_CMD_REQUEST_SENSE 0x03 +#define SCSI_CMD_TEST_UNIT_READY 0x00 +#define SCSI_CMD_INQUIRY 0x12 +#define SCSI_CMD_READ_10 0x28 +#define SCSI_CMD_READ_CAPACITY 0x25 +#define SCSI_CMD_WRITE_10 0x2A + +/* +************************************************************************************************************** +* TYPE DEFINITIONS +************************************************************************************************************** +*/ + +typedef enum ms_data_dir { + + MS_DATA_DIR_IN = 0x80, + MS_DATA_DIR_OUT = 0x00, + MS_DATA_DIR_NONE = 0x01 + +} MS_DATA_DIR; + +/* +************************************************************************************************************** +* FUNCTION PROTOTYPES +************************************************************************************************************** +*/ + +USB_INT32S MS_BulkRecv ( USB_INT32U block_number, + USB_INT16U num_blocks, + volatile USB_INT08U *user_buffer); + +USB_INT32S MS_BulkSend ( USB_INT32U block_number, + USB_INT16U num_blocks, + volatile USB_INT08U *user_buffer); +USB_INT32S MS_ParseConfiguration(void); +USB_INT32S MS_TestUnitReady (void); +USB_INT32S MS_ReadCapacity (USB_INT32U *numBlks, USB_INT32U *blkSize); +USB_INT32S MS_GetMaxLUN (void); +USB_INT32S MS_GetSenseInfo (void); +USB_INT32S MS_Init (USB_INT32U *blkSize, USB_INT32U *numBlks, USB_INT08U *inquiryResult); +USB_INT32S MS_Inquire (USB_INT08U *response); + +void Fill_MSCommand ( USB_INT32U block_number, + USB_INT32U block_size, + USB_INT16U num_blocks, + MS_DATA_DIR direction, + USB_INT08U scsi_cmd, + USB_INT08U scsi_cmd_len); +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/VmRecorderV1dot1.cpp Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,428 @@ +#include "mbed.h" +#include "MSCFileSystem.h" +#include "Configuracion.h" +#include "SistemaArchivos.h" +#include "FechaHora.h" +#include "SelecManager.h" +#include "ScreenManager.h" +#include "Portada.cpp" +#include "Menu.h" +#include "ListaSelec.h" +#include "IdiomaSelec.h" +#include "FormaSelec.h" +#include "VelAdquisicionSel.h" +#include "RestaurarValores.h" +#include "Mensaje.h" +#include "NuevoViaje.h" +#include "GuardarViaje.h" +#include "ArchivoGuardado.h" +#include "ViajesGuardados.h" +#include "Teclado.h" +#include "GuardarOtroNombre.h" +#include "OpcionesViaje.h" +#include "FechaHoraConf.h" +#include "AutoCalibracion.h" + +//DEFINICIONES +#define ESPANOL 0 +#define INGLES 1 + +/// PEN DRIVE /// +MSCFileSystem msc("usb"); + +/// MEMORIA FLASH LOCAL DE LA MBED /// +LocalFileSystem local("local"); // Create the local filesystem under the name "local" +Configuracion config = Configuracion(); +SistemaArchivos SA = SistemaArchivos(); + +// Fecha y hora +FechaHora FH; + +/******************************************** + PANTALLAS + ********************************************/ +SPI spi( p5, NC, p7 ); // MOSI, MISO, CLK +DogMLCD dog( spi, p10, p8); // SPI, CS, A0 + +ScreenManager SC(&dog); // Screen Manager +SelecManager SM; // gestiona las pantallas que tienen elementos seleccionables + +Portada portadaVm = Portada(); +Screen* pportadaVm = &portadaVm; + +Menu menu = Menu(); +Screen* pmenu = &menu; +Seleccion* psmenu = &menu; + +Teclado keyboard = Teclado(); +Screen* pkeyboard = &keyboard; +Seleccion* pskeyboard = &keyboard; + +ViajesGuardados listaViajes = ViajesGuardados("No existen viajes"); +Screen* plistaViajes = &listaViajes; +Seleccion* pslistaViajes = &listaViajes; + +ListaSelec configuracion = ListaSelec(); +Screen* pconfiguracion = &configuracion; +Seleccion* psconfiguracion = &configuracion; + +RestaurarValores restaurar = RestaurarValores("\250Est\240 seguro?"); +Screen* prestaurar = &restaurar; +Seleccion* psrestaurar = &restaurar; + +IdiomaSelec idioma = IdiomaSelec(); +Screen* pidioma = &idioma; +Seleccion* psidioma = &idioma; + +FormaSelec formaSelec = FormaSelec(); +Screen* pformaSelec = &formaSelec; +Seleccion* psformaSelec = &formaSelec; + +VelAdquisicionSel velAdquisionSel = VelAdquisicionSel(); +Screen* pvelAdquisionSel = &velAdquisionSel; +Seleccion* psvelAdquisionSel = &velAdquisionSel; + +NuevoViaje nuevoViaje = NuevoViaje("Adquiriendo datos", "Frecuencia: ", "OK para comenzar.", "OK para finalizar.", "Pulse atr\240s para cancelar."); +Screen* pnuevoViaje = &nuevoViaje; + +Mensaje noUSB = Mensaje("menu", "Pulse OK para volver."); +Screen* pnoUSB = &noUSB; + +GuardarOtroNombre guardadoCorrect = GuardarOtroNombre("menu", "Pulse OK para continuar.", "Espere por favor"); +Screen* pguardadoCorrect = &guardadoCorrect; + +GuardarViaje guardaViaje = GuardarViaje(); +Screen* pguardaViaje = &guardaViaje; +Seleccion* psguardaViaje = &guardaViaje; + +OpcionesViaje opcionesViaje = OpcionesViaje(); +Screen* popcionesViaje = &opcionesViaje; +Seleccion* psopcionesViaje = &opcionesViaje; + +ArchivoGuardado archivoGuardado = ArchivoGuardado("guardaViaje", "Pulse OK para continuar.", "Archivo guardado:", "Fecha:", "Hora:"); +Screen* parchivoGuardado = &archivoGuardado; + +Mensaje archivoBorrado = Mensaje("menu", "Pulse OK para continuar."); +Screen* parchivoBorrado = &archivoBorrado; + +Mensaje nombreExistente = Mensaje("guardaViaje", "Pulse OK para volver."); +Screen* pnombreExistente = &nombreExistente; + +FechaHoraConf fechaHoraConf = FechaHoraConf("Pulse las teclas arriba y", "abajo para cambiar los", "valores.", "Fecha:", "Hora:"); +Screen* pfechaHoraConf = &fechaHoraConf; +Seleccion* psfechaHoraConf = &fechaHoraConf; + +AutoCalibracion calibrando = AutoCalibracion(); +Screen* pcalibrando = &calibrando; + +// Inglés +Menu menuEN = Menu(); +Screen* pmenuEN = &menuEN; +Seleccion* psmenuEN = &menuEN; + +ViajesGuardados listaViajesEN = ViajesGuardados("No travels"); +Screen* plistaViajesEN = &listaViajesEN; +Seleccion* pslistaViajesEN = &listaViajesEN; + +ListaSelec configuracionEN = ListaSelec(); +Screen* pconfiguracionEN = &configuracionEN; +Seleccion* psconfiguracionEN = &configuracionEN; + +RestaurarValores restaurarEN = RestaurarValores("Are you sure?"); +Screen* prestaurarEN = &restaurarEN; +Seleccion* psrestaurarEN = &restaurarEN; + +IdiomaSelec idiomaEN = IdiomaSelec(); +Screen* pidiomaEN = &idiomaEN; +Seleccion* psidiomaEN = &idiomaEN; + +FormaSelec formaSelecEN = FormaSelec(); +Screen* pformaSelecEN = &formaSelecEN; +Seleccion* psformaSelecEN = &formaSelecEN; + +NuevoViaje nuevoViajeEN = NuevoViaje("Acquiring data", "Frecuency: ", "Press OK to start.", "Press OK to finish.", "Press back to cancel."); +Screen* pnuevoViajeEN = &nuevoViajeEN; + +Mensaje noUSBEN = Mensaje("menu", "Press OK to back."); +Screen* pnoUSBEN = &noUSBEN; + +GuardarOtroNombre guardadoCorrectEN = GuardarOtroNombre("menu", "Press OK to continue.", "Please wait"); +Screen* pguardadoCorrectEN = &guardadoCorrectEN; + +GuardarViaje guardaViajeEN = GuardarViaje(); +Screen* pguardaViajeEN = &guardaViajeEN; +Seleccion* psguardaViajeEN = &guardaViajeEN; + +OpcionesViaje opcionesViajeEN = OpcionesViaje(); +Screen* popcionesViajeEN = &opcionesViajeEN; +Seleccion* psopcionesViajeEN = &opcionesViajeEN; + +ArchivoGuardado archivoGuardadoEN = ArchivoGuardado("guardaViaje", "Press OK to continue.", "Saved file:", "date:", "Time:"); +Screen* parchivoGuardadoEN = &archivoGuardadoEN; + +Mensaje archivoBorradoEN = Mensaje("menu", "Press OK to continue."); +Screen* parchivoBorradoEN = &archivoBorradoEN; + +Mensaje nombreExistenteEN = Mensaje("guardaViaje", "Press OK to back."); +Screen* pnombreExistenteEN = &nombreExistenteEN; + +FechaHoraConf fechaHoraConfEN = FechaHoraConf("Press the up and down keys to change values.", "", "", "Date:", "Time:"); +Screen* pfechaHoraConfEN = &fechaHoraConfEN; +Seleccion* psfechaHoraConfEN = &fechaHoraConfEN; + +/********************************************/ + +/******************************************** + BOTONES + ********************************************/ +DigitalIn boton1(p30); +DigitalIn boton2(p29); +DigitalIn boton3(p28); +DigitalIn boton4(p27); +DigitalIn boton5(p26); +DigitalIn boton6(p14); +/********************************************/ + +DigitalOut myled(LED2); + +Timer t; + +int main() +{ + /******************************************** + PANTALLAS + ********************************************/ + /******************* Se añaden las pantallas al ScreenManager ******************************/ + + // Portada inicial + SC.addScreen(pportadaVm, "portada", ESPANOL); + SC.addScreen(pportadaVm, "portada", INGLES); + + // Menu principal + menu.addElement("Nuevo viaje", "viaje"); + menu.addElement("Viajes guardados", "listadoViajes"); + menu.addElement("Configuraci\242n", "configuracion"); + menu.setSelect(0); + SC.addScreen(pmenu, "menu", ESPANOL); + SM.addScreen(psmenu); + + menuEN.addElement("New ride", "viaje"); + menuEN.addElement("Saved rides", "listadoViajes"); + menuEN.addElement("Settings", "configuracion"); + menuEN.setSelect(0); + SC.addScreen(pmenuEN, "menu", INGLES); + SM.addScreen(psmenuEN); + + // Pantalla teclado + keyboard.setSelect(0); + SC.addScreen(pkeyboard, "teclado", ESPANOL); // El teclado es el mismo para todos los idiomas + SC.addScreen(pkeyboard, "teclado", INGLES); + SM.addScreen(pskeyboard); + + // Pantalla de autocalibración + SC.addScreen(pcalibrando, "calibrate", ESPANOL); // La pantalla de calibración es la misma para todos los idiomas (el idioma se controla en el propio código de la pantalla) + SC.addScreen(pcalibrando, "calibrate", INGLES); + + // Lista de viajes guardados + listaViajes.setBackScreen("menu"); + SC.addScreen(plistaViajes, "listadoViajes", ESPANOL); + SM.addScreen(pslistaViajes); + + listaViajesEN.setBackScreen("menu"); + SC.addScreen(plistaViajesEN, "listadoViajes", INGLES); + SM.addScreen(pslistaViajesEN); + + // Lista de configuración + configuracion.addElement("Velocidad de adquisici\242n", "velAdquisionSel"); + configuracion.addElement("Idioma", "idioma"); + configuracion.addElement("Visualizaci\242n", "formaSelec"); + configuracion.addElement("Ajustar fecha y hora", "confFecha"); + configuracion.addElement("Autocalibraci\242n", "calibrate"); + configuracion.addElement("Valores de f\240brica", "restaurar"); + configuracion.setBackScreen("menu"); + SC.addScreen(pconfiguracion, "configuracion", 0); + SM.addScreen(psconfiguracion); + + configuracionEN.addElement("Sample Rate", "velAdquisionSel"); + configuracionEN.addElement("Languaje", "idioma"); + configuracionEN.addElement("Visualization", "formaSelec"); + configuracionEN.addElement("Set date and time", "confFecha"); + configuracionEN.addElement("Autocalibration", "calibrate"); + configuracionEN.addElement("Restore default settings", "restaurar"); + configuracionEN.setBackScreen("menu"); + SC.addScreen(pconfiguracionEN, "configuracion", 1); + SM.addScreen(psconfiguracionEN); + + // Pantalla de restauración de datos de fábrica + restaurar.addElement("No restaurar", "configuracion"); + restaurar.addElement("resturar", "configuracion"); + restaurar.setBackScreen("configuracion"); + SC.addScreen(prestaurar, "restaurar", 0); + SM.addScreen(psrestaurar); + + restaurarEN.addElement("do not restore", "configuracion"); + restaurarEN.addElement("restore", "configuracion"); + restaurarEN.setBackScreen("configuracion"); + SC.addScreen(prestaurarEN, "restaurar", 1); + SM.addScreen(psrestaurarEN); + + // pantalla de selección de idioma + idioma.addElement("Espa\244ol", "configuracion"); + idioma.addElement("Ingl\202s", "configuracion"); + idioma.setBackScreen("configuracion"); + SC.addScreen(pidioma, "idioma", 0); + SM.addScreen(psidioma); + + idiomaEN.addElement("Spanish", "configuracion"); + idiomaEN.addElement("English", "configuracion"); + idiomaEN.setBackScreen("configuracion"); + SC.addScreen(pidiomaEN, "idioma", 1); + SM.addScreen(psidiomaEN); + + // Pantalla de selección de la forma de selección + formaSelec.addElement("Sombreado", "configuracion"); + formaSelec.addElement("Encuadrado", "configuracion"); + formaSelec.setBackScreen("configuracion"); + SC.addScreen(pformaSelec, "formaSelec", 0); + SM.addScreen(psformaSelec); + + formaSelecEN.addElement("Shading", "configuracion"); + formaSelecEN.addElement("Framing", "configuracion"); + formaSelecEN.setBackScreen("configuracion"); + SC.addScreen(pformaSelecEN, "formaSelec", 1); + SM.addScreen(psformaSelecEN); + + // Pantalla de selección de la velocidad de adquisición + velAdquisionSel.addElement("1000 Hz", "configuracion"); + velAdquisionSel.addElement("320 Hz", "configuracion"); + velAdquisionSel.setBackScreen("configuracion"); + SC.addScreen(pvelAdquisionSel, "velAdquisionSel", ESPANOL); + SC.addScreen(pvelAdquisionSel, "velAdquisionSel", INGLES); // Como sólo se muestran valores y sus unidades no es necesaria esta pantalla en otros idiomas + SM.addScreen(psvelAdquisionSel); + + // Pantalla de cambio de fecha y hora + fechaHoraConf.setSelect(0); + fechaHoraConf.setBackScreen("configuracion"); + SC.addScreen(pfechaHoraConf, "confFecha", ESPANOL); + SM.addScreen(psfechaHoraConf); + + fechaHoraConfEN.setSelect(0); + fechaHoraConfEN.setBackScreen("configuracion"); + SC.addScreen(pfechaHoraConfEN, "confFecha", INGLES); + SM.addScreen(psfechaHoraConfEN); + + // Pantalla de nuevo viaje + SC.addScreen(pnuevoViaje, "viaje", 0); + SC.addScreen(pnuevoViajeEN, "viaje", 1); + + // Mensaje de USB lleno o desconectado + noUSB.addElement("USB desconectado"); + noUSB.addElement("o lleno"); + noUSB.setBackScreen("menu"); + SC.addScreen(pnoUSB, "USBdesconectado", 0); + + noUSBEN.addElement("USB disconected"); + noUSBEN.addElement("or full"); + noUSBEN.setBackScreen("menu"); + SC.addScreen(pnoUSBEN, "USBdesconectado", 1); + + // Archivo guardado correctamente (Mensaje) + guardadoCorrect.addElement("Archivo guardado"); + guardadoCorrect.addElement("correctamente"); + guardadoCorrect.setBackScreen("menu"); + SC.addScreen(pguardadoCorrect, "fileSaved", ESPANOL); + + guardadoCorrectEN.addElement("File saved"); + guardadoCorrectEN.addElement("correctly"); + guardadoCorrectEN.setBackScreen("menu"); + SC.addScreen(pguardadoCorrectEN, "fileSaved", INGLES); + + // Pantalla de guardado de viaje + guardaViaje.addElement("Volver al men\243", "menu"); + //guardaViaje.addElement("Postprocesado", "menu"); + guardaViaje.addElement("Cambiar nombre", "teclado"); + guardaViaje.addElement("Borrar", "archivoBorrado"); + guardaViaje.setSelect(0); + SC.addScreen(pguardaViaje, "guardaViaje", ESPANOL); + SM.addScreen(psguardaViaje); + + guardaViajeEN.addElement("Back to menu", "menu"); + //guardaViajeEN.addElement("Postprocessing", "menu"); + guardaViajeEN.addElement("Rename", "teclado"); + guardaViajeEN.addElement("Delete", "archivoBorrado"); + guardaViajeEN.setSelect(0); + SC.addScreen(pguardaViajeEN, "guardaViaje", INGLES); + SM.addScreen(psguardaViajeEN); + + // Pantalla de las opciones de un viaje cuando accedes a él mediante la lista de viajes + opcionesViaje.addElement("Cambiar nombre", "teclado"); + opcionesViaje.addElement("Borrar", "listadoViajes"); + opcionesViaje.setSelect(0); + opcionesViaje.setBackScreen("listadoViajes"); + SC.addScreen(popcionesViaje, "rOptions", ESPANOL); + SM.addScreen(psopcionesViaje); + + opcionesViajeEN.addElement("Rename", "teclado"); + opcionesViajeEN.addElement("Delete", "listadoViajes"); + opcionesViajeEN.setSelect(0); + opcionesViajeEN.setBackScreen("listadoViajes"); + SC.addScreen(popcionesViajeEN, "rOptions", INGLES); + SM.addScreen(psopcionesViajeEN); + + // Mensaje de archivo guardado + SC.addScreen(parchivoGuardado, "archivoGuardado", ESPANOL); + SC.addScreen(parchivoGuardadoEN, "archivoGuardado", INGLES); + + // Mensaje de archivo borrado + archivoBorrado.addElement("Viaje borrado"); + archivoBorrado.addElement("correctamente"); + archivoBorrado.setBackScreen("menu"); + SC.addScreen(parchivoBorrado, "archivoBorrado", ESPANOL); + + archivoBorradoEN.addElement("Deleted file"); + archivoBorradoEN.addElement("corretly"); + archivoBorradoEN.setBackScreen("menu"); + SC.addScreen(parchivoBorradoEN, "archivoBorrado", INGLES); + + // Mensade de existencia de un viaje con el mismo nombre + nombreExistente.addElement("Ya existe un"); + nombreExistente.addElement("viaje con el"); + nombreExistente.addElement("nombre introducido."); + nombreExistente.setBackScreen("guardaViaje"); + SC.addScreen(pnombreExistente, "alredyExist", ESPANOL); + + nombreExistenteEN.addElement("Alredy exist a"); + nombreExistenteEN.addElement("ride with the"); + nombreExistenteEN.addElement("entered name"); + nombreExistenteEN.setBackScreen("guardaViaje"); + SC.addScreen(pnombreExistenteEN, "alredyExist", INGLES); + + /****************************************/ + + /******************************************** + CARGA DE LA CONFIGURACIÓN + ********************************************/ + char aux[16]; + // Se selecciona el idioma + config.getIdioma(aux); + if(strcmp(aux, "spanish") == 0){ + SC.selectGroup(0); + }else if(strcmp(aux, "english") == 0){ + SC.selectGroup(1); + } + + // Se selecciona el modo de selección + config.getFormaSeleccion(aux); + if(strcmp(aux, "shading") == 0){ + SM.setInverterSelection(); + }else if(strcmp(aux, "framing") == 0){ + SM.setRectSelection(); + } + + /****************************************/ + + SC.initialize(); + while(1){ + SC.update(); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Mon Jun 15 15:34:27 2015 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/04dd9b1680ae \ No newline at end of file