test code megasquirt and digole lcd
Dependencies: FatFileSystem mbed
Revision 0:7ea8f0d27a4f, committed 2015-11-27
- Comitter:
- jpnovak
- Date:
- Fri Nov 27 16:32:41 2015 +0000
- Commit message:
- test code megasquirt digole;
Changed in this revision
diff -r 000000000000 -r 7ea8f0d27a4f FATFileSystem.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FATFileSystem.lib Fri Nov 27 16:32:41 2015 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_unsupported/code/FatFileSystem/#333d6e93e58f
diff -r 000000000000 -r 7ea8f0d27a4f LIS302.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LIS302.lib Fri Nov 27 16:32:41 2015 +0000 @@ -0,0 +1,1 @@ +http://mbed.org \ No newline at end of file
diff -r 000000000000 -r 7ea8f0d27a4f SDFileSystem.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SDFileSystem.cpp Fri Nov 27 16:32:41 2015 +0000 @@ -0,0 +1,457 @@ +/* mbed SDFileSystem Library, for providing file access to SD cards + * Copyright (c) 2008-2010, sford + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/* Introduction + * ------------ + * SD and MMC cards support a number of interfaces, but common to them all + * is one based on SPI. This is the one I'm implmenting because it means + * it is much more portable even though not so performant, and we already + * have the mbed SPI Interface! + * + * The main reference I'm using is Chapter 7, "SPI Mode" of: + * http://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf + * + * SPI Startup + * ----------- + * The SD card powers up in SD mode. The SPI interface mode is selected by + * asserting CS low and sending the reset command (CMD0). The card will + * respond with a (R1) response. + * + * CMD8 is optionally sent to determine the voltage range supported, and + * indirectly determine whether it is a version 1.x SD/non-SD card or + * version 2.x. I'll just ignore this for now. + * + * ACMD41 is repeatedly issued to initialise the card, until "in idle" + * (bit 0) of the R1 response goes to '0', indicating it is initialised. + * + * You should also indicate whether the host supports High Capicity cards, + * and check whether the card is high capacity - i'll also ignore this + * + * SPI Protocol + * ------------ + * The SD SPI protocol is based on transactions made up of 8-bit words, with + * the host starting every bus transaction by asserting the CS signal low. The + * card always responds to commands, data blocks and errors. + * + * The protocol supports a CRC, but by default it is off (except for the + * first reset CMD0, where the CRC can just be pre-calculated, and CMD8) + * I'll leave the CRC off I think! + * + * Standard capacity cards have variable data block sizes, whereas High + * Capacity cards fix the size of data block to 512 bytes. I'll therefore + * just always use the Standard Capacity cards with a block size of 512 bytes. + * This is set with CMD16. + * + * You can read and write single blocks (CMD17, CMD25) or multiple blocks + * (CMD18, CMD25). For simplicity, I'll just use single block accesses. When + * the card gets a read command, it responds with a response token, and then + * a data token or an error. + * + * SPI Command Format + * ------------------ + * Commands are 6-bytes long, containing the command, 32-bit argument, and CRC. + * + * +---------------+------------+------------+-----------+----------+--------------+ + * | 01 | cmd[5:0] | arg[31:24] | arg[23:16] | arg[15:8] | arg[7:0] | crc[6:0] | 1 | + * +---------------+------------+------------+-----------+----------+--------------+ + * + * As I'm not using CRC, I can fix that byte to what is needed for CMD0 (0x95) + * + * All Application Specific commands shall be preceded with APP_CMD (CMD55). + * + * SPI Response Format + * ------------------- + * The main response format (R1) is a status byte (normally zero). Key flags: + * idle - 1 if the card is in an idle state/initialising + * cmd - 1 if an illegal command code was detected + * + * +-------------------------------------------------+ + * R1 | 0 | arg | addr | seq | crc | cmd | erase | idle | + * +-------------------------------------------------+ + * + * R1b is the same, except it is followed by a busy signal (zeros) until + * the first non-zero byte when it is ready again. + * + * Data Response Token + * ------------------- + * Every data block written to the card is acknowledged by a byte + * response token + * + * +----------------------+ + * | xxx | 0 | status | 1 | + * +----------------------+ + * 010 - OK! + * 101 - CRC Error + * 110 - Write Error + * + * Single Block Read and Write + * --------------------------- + * + * Block transfers have a byte header, followed by the data, followed + * by a 16-bit CRC. In our case, the data will always be 512 bytes. + * + * +------+---------+---------+- - - -+---------+-----------+----------+ + * | 0xFE | data[0] | data[1] | | data[n] | crc[15:8] | crc[7:0] | + * +------+---------+---------+- - - -+---------+-----------+----------+ + */ + +#include "SDFileSystem.h" + +#define SD_COMMAND_TIMEOUT 5000 + +SDFileSystem::SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name) : + FATFileSystem(name), _spi(mosi, miso, sclk), _cs(cs) { + _cs = 1; +} + +#define R1_IDLE_STATE (1 << 0) +#define R1_ERASE_RESET (1 << 1) +#define R1_ILLEGAL_COMMAND (1 << 2) +#define R1_COM_CRC_ERROR (1 << 3) +#define R1_ERASE_SEQUENCE_ERROR (1 << 4) +#define R1_ADDRESS_ERROR (1 << 5) +#define R1_PARAMETER_ERROR (1 << 6) + +// Types +// - v1.x Standard Capacity +// - v2.x Standard Capacity +// - v2.x High Capacity +// - Not recognised as an SD Card + +#define SDCARD_FAIL 0 +#define SDCARD_V1 1 +#define SDCARD_V2 2 +#define SDCARD_V2HC 3 + +int SDFileSystem::initialise_card() { + // Set to 100kHz for initialisation, and clock card with cs = 1 + _spi.frequency(100000); + _cs = 1; + for(int i=0; i<16; i++) { + _spi.write(0xFF); + } + + // send CMD0, should return with all zeros except IDLE STATE set (bit 0) + if(_cmd(0, 0) != R1_IDLE_STATE) { + fprintf(stderr, "No disk, or could not put SD card in to SPI idle state\n"); + return SDCARD_FAIL; + } + + // send CMD8 to determine whther it is ver 2.x + int r = _cmd8(); + if(r == R1_IDLE_STATE) { + return initialise_card_v2(); + } else if(r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) { + return initialise_card_v1(); + } else { + fprintf(stderr, "Not in idle state after sending CMD8 (not an SD card?)\n"); + return SDCARD_FAIL; + } +} + +int SDFileSystem::initialise_card_v1() { + for(int i=0; i<SD_COMMAND_TIMEOUT; i++) { + _cmd(55, 0); + if(_cmd(41, 0) == 0) { + return SDCARD_V1; + } + } + + fprintf(stderr, "Timeout waiting for v1.x card\n"); + return SDCARD_FAIL; +} + +int SDFileSystem::initialise_card_v2() { + + for(int i=0; i<SD_COMMAND_TIMEOUT; i++) { + _cmd(55, 0); + if(_cmd(41, 0) == 0) { + _cmd58(); + return SDCARD_V2; + } + } + + fprintf(stderr, "Timeout waiting for v2.x card\n"); + return SDCARD_FAIL; +} + +int SDFileSystem::disk_initialize() { + + int i = initialise_card(); +// printf("init card = %d\n", i); +// printf("OK\n"); + + _sectors = _sd_sectors(); + + // Set block length to 512 (CMD16) + if(_cmd(16, 512) != 0) { + fprintf(stderr, "Set 512-byte block timed out\n"); + return 1; + } + + _spi.frequency(1000000); // Set to 1MHz for data transfer + return 0; +} + +int SDFileSystem::disk_write(const char *buffer, int block_number) { + // set write address for single block (CMD24) + if(_cmd(24, block_number * 512) != 0) { + return 1; + } + + // send the data block + _write(buffer, 512); + return 0; +} + +int SDFileSystem::disk_read(char *buffer, int block_number) { + // set read address for single block (CMD17) + if(_cmd(17, block_number * 512) != 0) { + return 1; + } + + // receive the data + _read(buffer, 512); + return 0; +} + +int SDFileSystem::disk_status() { return 0; } +int SDFileSystem::disk_sync() { return 0; } +int SDFileSystem::disk_sectors() { return _sectors; } + +// PRIVATE FUNCTIONS + +int SDFileSystem::_cmd(int cmd, int arg) { + _cs = 0; + + // send a command + _spi.write(0x40 | cmd); + _spi.write(arg >> 24); + _spi.write(arg >> 16); + _spi.write(arg >> 8); + _spi.write(arg >> 0); + _spi.write(0x95); + + // wait for the repsonse (response[7] == 0) + for(int i=0; i<SD_COMMAND_TIMEOUT; i++) { + int response = _spi.write(0xFF); + if(!(response & 0x80)) { + _cs = 1; + _spi.write(0xFF); + return response; + } + } + _cs = 1; + _spi.write(0xFF); + return -1; // timeout +} +int SDFileSystem::_cmdx(int cmd, int arg) { + _cs = 0; + + // send a command + _spi.write(0x40 | cmd); + _spi.write(arg >> 24); + _spi.write(arg >> 16); + _spi.write(arg >> 8); + _spi.write(arg >> 0); + _spi.write(0x95); + + // wait for the repsonse (response[7] == 0) + for(int i=0; i<SD_COMMAND_TIMEOUT; i++) { + int response = _spi.write(0xFF); + if(!(response & 0x80)) { + return response; + } + } + _cs = 1; + _spi.write(0xFF); + return -1; // timeout +} + + +int SDFileSystem::_cmd58() { + _cs = 0; + int arg = 0; + + // send a command + _spi.write(0x40 | 58); + _spi.write(arg >> 24); + _spi.write(arg >> 16); + _spi.write(arg >> 8); + _spi.write(arg >> 0); + _spi.write(0x95); + + // wait for the repsonse (response[7] == 0) + for(int i=0; i<SD_COMMAND_TIMEOUT; i++) { + int response = _spi.write(0xFF); + if(!(response & 0x80)) { + int ocr = _spi.write(0xFF) << 24; + ocr |= _spi.write(0xFF) << 16; + ocr |= _spi.write(0xFF) << 8; + ocr |= _spi.write(0xFF) << 0; +// printf("OCR = 0x%08X\n", ocr); + _cs = 1; + _spi.write(0xFF); + return response; + } + } + _cs = 1; + _spi.write(0xFF); + return -1; // timeout +} + +int SDFileSystem::_cmd8() { + _cs = 0; + + // send a command + _spi.write(0x40 | 8); // CMD8 + _spi.write(0x00); // reserved + _spi.write(0x00); // reserved + _spi.write(0x01); // 3.3v + _spi.write(0xAA); // check pattern + _spi.write(0x87); // crc + + // wait for the repsonse (response[7] == 0) + for(int i=0; i<SD_COMMAND_TIMEOUT * 1000; i++) { + char response[5]; + response[0] = _spi.write(0xFF); + if(!(response[0] & 0x80)) { + for(int j=1; j<5; j++) { + response[i] = _spi.write(0xFF); + } + _cs = 1; + _spi.write(0xFF); + return response[0]; + } + } + _cs = 1; + _spi.write(0xFF); + return -1; // timeout +} + +int SDFileSystem::_read(char *buffer, int length) { + _cs = 0; + + // read until start byte (0xFF) + while(_spi.write(0xFF) != 0xFE); + + // read data + for(int i=0; i<length; i++) { + buffer[i] = _spi.write(0xFF); + } + _spi.write(0xFF); // checksum + _spi.write(0xFF); + + _cs = 1; + _spi.write(0xFF); + return 0; +} + +int SDFileSystem::_write(const char *buffer, int length) { + _cs = 0; + + // indicate start of block + _spi.write(0xFE); + + // write the data + for(int i=0; i<length; i++) { + _spi.write(buffer[i]); + } + + // write the checksum + _spi.write(0xFF); + _spi.write(0xFF); + + // check the repsonse token + if((_spi.write(0xFF) & 0x1F) != 0x05) { + _cs = 1; + _spi.write(0xFF); + return 1; + } + + // wait for write to finish + while(_spi.write(0xFF) == 0); + + _cs = 1; + _spi.write(0xFF); + return 0; +} + +static int ext_bits(char *data, int msb, int lsb) { + int bits = 0; + int size = 1 + msb - lsb; + for(int i=0; i<size; i++) { + int position = lsb + i; + int byte = 15 - (position >> 3); + int bit = position & 0x7; + int value = (data[byte] >> bit) & 1; + bits |= value << i; + } + return bits; +} + +int SDFileSystem::_sd_sectors() { + + // CMD9, Response R2 (R1 byte + 16-byte block read) + if(_cmdx(9, 0) != 0) { + fprintf(stderr, "Didn't get a response from the disk\n"); + return 0; + } + + char csd[16]; + if(_read(csd, 16) != 0) { + fprintf(stderr, "Couldn't read csd response from disk\n"); + return 0; + } + + // csd_structure : csd[127:126] + // c_size : csd[73:62] + // c_size_mult : csd[49:47] + // read_bl_len : csd[83:80] - the *maximum* read block length + + int csd_structure = ext_bits(csd, 127, 126); + int c_size = ext_bits(csd, 73, 62); + int c_size_mult = ext_bits(csd, 49, 47); + int read_bl_len = ext_bits(csd, 83, 80); + +// printf("CSD_STRUCT = %d\n", csd_structure); + + if(csd_structure != 0) { + fprintf(stderr, "This disk tastes funny! I only know about type 0 CSD structures\n"); + return 0; + } + + // memory capacity = BLOCKNR * BLOCK_LEN + // where + // BLOCKNR = (C_SIZE+1) * MULT + // MULT = 2^(C_SIZE_MULT+2) (C_SIZE_MULT < 8) + // BLOCK_LEN = 2^READ_BL_LEN, (READ_BL_LEN < 12) + + int block_len = 1 << read_bl_len; + int mult = 1 << (c_size_mult + 2); + int blocknr = (c_size + 1) * mult; + int capacity = blocknr * block_len; + + int blocks = capacity / 512; + + return blocks; +}
diff -r 000000000000 -r 7ea8f0d27a4f SDFileSystem.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SDFileSystem.h Fri Nov 27 16:32:41 2015 +0000 @@ -0,0 +1,81 @@ +/* mbed SDFileSystem Library, for providing file access to SD cards + * Copyright (c) 2008-2010, sford + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MBED_SDFILESYSTEM_H +#define MBED_SDFILESYSTEM_H + +#include "mbed.h" +#include "FATFileSystem.h" + +/** Access the filesystem on an SD Card using SPI + * + * @code + * #include "mbed.h" + * #include "SDFileSystem.h" + * + * SDFileSystem sd(p5, p6, p7, p12, "sd"); // mosi, miso, sclk, cs + * + * int main() { + * FILE *fp = fopen("/sd/myfile.txt", "w"); + * fprintf(fp, "Hello World!\n"); + * fclose(fp); + * } + */ +class SDFileSystem : public FATFileSystem { +public: + + /** Create the File System for accessing an SD Card using SPI + * + * @param mosi SPI mosi pin connected to SD Card + * @param miso SPI miso pin conencted to SD Card + * @param sclk SPI sclk pin connected to SD Card + * @param cs DigitalOut pin used as SD Card chip select + * @param name The name used to access the virtual filesystem + */ + SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name); + virtual int disk_initialize(); + virtual int disk_write(const char *buffer, int block_number); + virtual int disk_read(char *buffer, int block_number); + virtual int disk_status(); + virtual int disk_sync(); + virtual int disk_sectors(); + +protected: + + int _cmd(int cmd, int arg); + int _cmdx(int cmd, int arg); + int _cmd8(); + int _cmd58(); + int initialise_card(); + int initialise_card_v1(); + int initialise_card_v2(); + + int _read(char *buffer, int length); + int _write(const char *buffer, int length); + int _sd_sectors(); + int _sectors; + + SPI _spi; + DigitalOut _cs; +}; + +#endif
diff -r 000000000000 -r 7ea8f0d27a4f SerialBuffered.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SerialBuffered.cpp Fri Nov 27 16:32:41 2015 +0000 @@ -0,0 +1,108 @@ + +#include "mbed.h" +#include "SerialBuffered.h" + +extern Serial loggerSerial; + +SerialBuffered::SerialBuffered( size_t bufferSize, PinName tx, PinName rx ) : Serial( tx, rx ) +{ + m_buffSize = 0; + m_contentStart = 0; + m_contentEnd = 0; + m_timeout = 1.0; + + + attach( this, &SerialBuffered::handleInterrupt ); + + m_buff = (uint8_t *) malloc( bufferSize ); + if( m_buff == NULL ) + { + //loggerSerial.printf("SerialBuffered - failed to alloc buffer size %d\r\n", (int) bufferSize ); + } + else + { + m_buffSize = bufferSize; + } +} + + +SerialBuffered::~SerialBuffered() +{ + if( m_buff ) + free( m_buff ); +} + +void SerialBuffered::setTimeout( float seconds ) +{ + m_timeout = seconds; +} + +size_t SerialBuffered::readBytes( uint8_t *bytes, size_t requested ) +{ + int i = 0; + + for( ; i < requested; ) + { + int c = getc(); + if( c < 0 ) + break; + bytes[i] = c; + i++; + } + + return i; + +} + + +int SerialBuffered::getc() +{ + m_timer.reset(); + m_timer.start(); + while( m_contentStart == m_contentEnd ) + { + + + wait_ms( 1 ); + if( m_timeout > 0 && m_timer.read() > m_timeout ) + return EOF; + } + + m_timer.stop(); + + uint8_t result = m_buff[m_contentStart++]; + m_contentStart = m_contentStart % m_buffSize; + + + return result; +} + + +int SerialBuffered::readable() +{ + return m_contentStart != m_contentEnd ; +} + +void SerialBuffered::handleInterrupt() +{ + + while( Serial::readable()) + { + if( m_contentStart == (m_contentEnd +1) % m_buffSize) + { + loggerSerial.printf("SerialBuffered - buffer overrun, data lost!\r\n" ); + Serial::getc(); + + } + else + { + + m_buff[ m_contentEnd ++ ] = Serial::getc(); + m_contentEnd = m_contentEnd % m_buffSize; + + + + } + } +} +
diff -r 000000000000 -r 7ea8f0d27a4f SerialBuffered.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SerialBuffered.h Fri Nov 27 16:32:41 2015 +0000 @@ -0,0 +1,39 @@ +#pragma once + +// This is a buffered serial reading class, using the serial interrupt introduced in mbed library version 18 on 17/11/09 + +// In the simplest case, construct it with a buffer size at least equal to the largest message you +// expect your program to receive in one go. + +class SerialBuffered : public Serial +{ +public: + SerialBuffered( size_t bufferSize, PinName tx, PinName rx ); + virtual ~SerialBuffered(); + + int getc(); // will block till the next character turns up, or return -1 if there is a timeout + + int readable(); // returns 1 if there is a character available to read, 0 otherwise + + void setTimeout( float seconds ); // maximum time in seconds that getc() should block + // while waiting for a character + // Pass -1 to disable the timeout. + + size_t readBytes( uint8_t *bytes, size_t requested ); // read requested bytes into a buffer, + // return number actually read, + // which may be less than requested if there has been a timeout + + +private: + + void handleInterrupt(); + + + uint8_t *m_buff; // points at a circular buffer, containing data from m_contentStart, for m_contentSize bytes, wrapping when you get to the end + uint16_t m_contentStart; // index of first bytes of content + uint16_t m_contentEnd; // index of bytes after last byte of content + uint16_t m_buffSize; + float m_timeout; + Timer m_timer; + +}; \ No newline at end of file
diff -r 000000000000 -r 7ea8f0d27a4f TextLCD.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TextLCD.cpp Fri Nov 27 16:32:41 2015 +0000 @@ -0,0 +1,188 @@ +/* draft mbed TextLCD + * (c) 2007/8, sford + */ + +#include "TextLCD.h" + +#include "mbed.h" + +using namespace mbed; + +/* + * useful info found at http://www.a-netz.de/lcd.en.php + * + * + * Initialisation + * ============== + * + * After attaching the supply voltage/after a reset, the display needs to be brought in to a defined state + * + * - wait approximately 15 ms so the display is ready to execute commands + * - Execute the command 0x30 ("Display Settings") three times (wait 1,64ms after each command, the busy flag cannot be queried now). + * - The display is in 8 bit mode, so if you have only connected 4 data pins you should only transmit the higher nibble of each command. + * - If you want to use the 4 bit mode, now you can execute the command to switch over to this mode now. + * - Execute the "clear display" command + * + * Timing + * ====== + * + * Nearly all commands transmitted to the display need 40us for execution. + * Exceptions are the commands "Clear Display and Reset" and "Set Cursor to Start Position" + * These commands need 1.64ms for execution. These timings are valid for all displays working with an + * internal clock of 250kHz. But I do not know any displays that use other frequencies. Any time you + * can use the busy flag to test if the display is ready to accept the next command. + * + * _e is kept high apart from calling clock + * _rw is kept 0 (write) apart from actions that uyse it differently + * _rs is set by the data/command writes + */ + + +//wait(0.05); + +TextLCD::TextLCD(PinName rs, PinName rw, PinName e, PinName d0, PinName d1, + PinName d2, PinName d3, int columns, int rows) : _rw(rw), _rs(rs), + _e(e), _d(d0, d1, d2, d3), _columns(columns), _rows(rows) { + + _rows = 4; + _columns = 20; +wait(0.05); + _rw = 0; + _e = 1; + _rs = 0; // command mode +wait(0.05); + // Should theoretically wait 15ms, but most things will be powered up pre-reset + // so i'll disable that for the minute. If implemented, could wait 15ms post reset + // instead + // wait(0.015); + + // send "Display Settings" 3 times (Only top nibble of 0x30 as we've got 4-bit bus) + for(int i=0; i<3; i++) { + writeNibble(0x3); + wait(0.005); // this command takes 1.64ms, so wait for it + } + wait(0.1); + writeNibble(0x2); // 4-bit mode +wait(0.001); + writeCommand(0x28); // Function set 001 BW N F - - +wait(0.001); + writeCommand(0x0C); + wait(0.001); + writeCommand(0x6); // Cursor Direction and Display Shift : 0000 01 CD S (CD 0-left, 1-right S(hift) 0-no, 1-yes + cls(); +} + + + +int TextLCD::_putc(int value) { + if(value == '\n') { + newline(); + } else { + writeData(value); + } + return value; +} + +int TextLCD::_getc() { + return 0; +} + +void TextLCD::newline() { + _column = 0; + _row++; + if(_row >= _rows) { + _row = 0; + } + locate(_column, _row); +} + +void TextLCD::locate(int column, int row) +{ + /* if(column < 0 || column >= _columns || row < 0 || row >= _rows) { + ERROR("locate(%d,%d) out of range on %dx%d display", column, row, _columns, _rows); + return; + }*/ + + _row = row; + _column = column; + int address=0; + + if (_rows > 2) { + // row 0 : 0x0->0x13 + // row 1 : 0x40->0x53 + // row 2 : 0x14->0x27 + // row 3 : 0x54->0x67 + + switch (_row) { + case (0) : address = 0x80 + _column; + break; + case (1) : address = 0xc0 + _column; + break; + case (2) : address = 0x94 + _column; + break; + case (3) : address = 0xd4 + _column; + break; + } + + } + else { + // memory starts at 0x80, and is 40 chars long per row + address = 0x80 + (_row * 40) + _column; + } + + writeCommand(address); +} + + +void TextLCD::rows(int rows) { + _rows = rows; +} + + +void TextLCD::columns(int columns) { + _columns = columns; +} + + + + +void TextLCD::cls() { + writeCommand(0x01); // Clear Display + wait(0.00164f); // This command takes 1.64 ms + locate(0, 0); +} + +void TextLCD::reset() { + cls(); +} + +void TextLCD::clock() { + wait(0.00010); + _e = 0; + wait(0.00010); // most instructions take 40us + _e = 1; +} + +void TextLCD::writeNibble(int value) { + _d = value; + clock(); +} + +void TextLCD::writeByte(int value) { + writeNibble(value >> 4); + writeNibble(value >> 0); +} + +void TextLCD::writeCommand(int command) { + _rs = 0; + writeByte(command); +} + +void TextLCD::writeData(int data) { + _rs = 1; + writeByte(data); + _column++; + if(_column >= _columns) { + newline(); + } +}
diff -r 000000000000 -r 7ea8f0d27a4f TextLCD.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TextLCD.h Fri Nov 27 16:32:41 2015 +0000 @@ -0,0 +1,51 @@ +/* draft mbed TextLCD + * (c) 2007/8, sford + */ + +#ifndef MBED_TEXTLCD_H +#define MBED_TEXTLCD_H + +#include "Stream.h" +#include "DigitalOut.h" +#include "BusOut.h" + +namespace mbed { + +class TextLCD : public Stream { + +public: + + TextLCD(PinName rs, PinName rw,PinName e, PinName d0, PinName d1, PinName d2, PinName d3, int columns, int rows); + void rows(int rows); + void columns(int columns); + + virtual void locate(int row, int column); + virtual void cls(); + virtual void reset(); +// virtual void init_Display(); + + +protected: + + void clock(); + void writeData(int data); + void writeCommand(int command); + void writeByte(int value); + void writeNibble(int value); + virtual int _putc(int c); + virtual int _getc(); + virtual void newline(); + + + int _rows; + int _columns; + int _row; + int _column; + DigitalOut _rw, _rs, _e; + BusOut _d; + +}; + +} + +#endif
diff -r 000000000000 -r 7ea8f0d27a4f main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Fri Nov 27 16:32:41 2015 +0000 @@ -0,0 +1,455 @@ +//Code Designed to display run-time variables from a Megasquirt Fuel Injection controller. +//This is the base code to load variables and print to DigoleSerialDisp and write them to a file. File format is .FRD for import into EFI Analytics tuner Studio + +#include "mbed.h" +//#include "TextDigoleSerialDisp.h" +#include "SDFileSystem.h" +#include "SerialBuffered.h" +//#include "LIS302.h" + + +//SD Card pin assignment +SDFileSystem sd(p11, p12, p13, p14, "sd");//DI, D0, SCK, CS + +AnalogIn SDenable(p20);//define SD card switch +DigitalOut myled1(LED1);//define LED +Serial loggerSerial(USBTX, USBRX); +Timer t; + +LocalFileSystem local("local"); + + + +//Serial usb(USBTX, USBRX); //define USB connection pins +SerialBuffered megasquirt(120, p28, p27); // that 128 is the size of the read buffer it will make for you + +Serial DigoleSerialDisp(p9, p10);//UART DigoleSerialDisp(PinName TX, PinName RX); + +DigitalOut usb_activity(LED1); //define USB activity +DigitalOut megasquirt_activity(LED2); //define Megasquirt activity +unsigned char tmp_data[16]; +unsigned char buf[120]; +int tmp; +float Time; +long float SecL; //get secoonds +long float PW;//get pulseWidth1 +long float PW2; //get pulseWidth2 +int RPM; //get Rpm +float DutyCycle; //Injector Duty Cycle +float DutyCycle2; //Injector Bank2 Duty Cycle +long float SparkAdv; //get advance +float squirt; //get squirt +float Engine; //get squirt +float afrtgt1; //get AFR target - Table 1 +float afrtgt2; //get AFR target - Table 2 +float wbo2_en1; //get WideBand Valid1 +float wbo2_en2; //get WideBand Valid2 +long float barometer; //get Barometer +long float MAP; //get manifold absolute pressure MAP +long float MAT; //get manifold absolute temperature (MAT) +long float CLT; //get coolant temperature (CLT) +long float TP; //get Throttle Position Sensor (TPS) +long float vBatt; //get BAttery Voltage +long float AFR; //get Realtime AFR for VE1 +long float AFR2; //get Realtime AFR for VE2 +long float knock; //get Knock Threshold Value +long float Gego; //get egoCorrrection1 amount % +long float Gego2; //get egoCorrrection2 amount % +long float Gair; //get air correction (G_air) +long float Gwarmup; //get Warmup Enrichment +long float TPSacc; //get accel enrichment (ms) +long float TPScut; //get TPS based fuel cut % +long float Gbaro; //get baroCorrection % +long float Gammae; //get gammaEnrich % +long float veCurr1; //get Current VE value Table 1 +long float veCurr2; //get Current VE value Table 2 +long float IAC; //get IAC Step % +long float ColdAdv; //get Cold Ignition Advance +long float tpsDOT; //get Rate of Change TPS +long float mapDOT; //get Rate of Change MAP +long float Dwell; //get Ignition Dwell +long float maf; //get MAF - Mass Air Flow +long float fuelload; //get MAP/TPS Blend % +long float Ethanol; //get fuel load percent alchohol +char portstatus; //get Spare Port Status +char knockRetard; //get Knock timing retard (deg) +long float EAEFuelCorr; //get EAE Fuel correction +long float egoV; //get egoV +long float egoV2; //get egoV2 +char status1; //get Status1 +char status2; //get Status2 +char status3; //get Status3 +char status4; //get Status4 +long float looptime; //get looptime +char status5; //get Status5 +long float tpsADC; //get tpsADC +long float fuelload2; //get fuelload2 +long float ignload; //get ignload +long float ignload2; //get ignload2 +char syncstatus; //get Sync-Status (0 - sync-error, 1 - syncstatus) +float deltaT; //get deltaT +long float wallfuel; //get wallfuel + +int runtime; + + +unsigned char data_out; +int n; +int row; +int column; +int i; +char MSII_288Header[] = {0x46,0x52,0x44,0x00,0x00,0x00,0x00,0x01,0x4b,0x61,0xf1,0x63,0x4d,0x53,0x49,0x49,0x20,0x52,0x65,0x76,0x20,0x32,0x2e,0x38,0x38,0x30,0x30,0x30,0x20,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x00,0x70};//file header +char MSIIExtraHeader[] = {0x46,0x52,0x44,0x00,0x00,0x00,0x00,0x01,0x4b,0x6a,0xf3,0xa8,0x4d,0x53,0x32,0x45,0x78,0x74,0x72,0x61,0x20,0x52,0x65,0x6c,0x20,0x32,0x2e,0x31,0x2e,0x31,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x00,0x91}; +char parse_header[] = {0x01,0x00};//data header + + +/*DigoleSerialDisp 2x20 parallel code pin assignment*/ +//TextDigoleSerialDisp DigoleSerialDisp(p21, p22, p23, p24, p25, p26, p30, 20, 2); // (rs, rw, e, d0, d1, d2, d3, n_column, n_rows) +//define file write +//AnalogIn file_writeenable(p20);//define SD card switch + + +//enter main loop +int main() { + + + DigoleSerialDisp.baud(9600);//set Digole Serial Baud Rate +// unsigned char tmp; +// unsigned char data_in; + +/////Startup Screen//////////// +DigoleSerialDisp.printf("CL\r");//clear screen +//DigoleSerialDisp.init_Display(); +//DigitalOut myled(LED1); +DigoleSerialDisp.printf(" DashView V2.1 "); +wait(3); +DigoleSerialDisp.printf("CL\r");//clear screen +DigoleSerialDisp.printf("SD3\r\n");//set rotation 0=0deg,1=90deg,2=180deg,3=270deg +DigoleSerialDisp.printf("TRT");//offset Line 1 in housing +DigoleSerialDisp.printf("SF3\rTT Have a great drive\r\n"); +DigoleSerialDisp.printf("TRT");//next line + +////////////End Startup Screen////////// + megasquirt.baud(115200); //define MEgasquirt serial speed + loggerSerial.baud(115200); //define USB connection speed +/* +//file header setup + FILE *fp = fopen("/sd/datalog.csv", "a"); + //print header for MS.csv file + fprintf(fp, "MSII Rev 2.88000, \nTime,SecL,RPM,MAP,TP,vBatt,AFR,MAT,CLT,Engine,Gego,Gair,Gwarm,Gbaro,Gammae,TPSacc,PW,DutyCycle,PW2,DutyCycle2,SparkAdv,ColdAdv,Dwell,tpsDOT,mapDOT,IAC,deltaT,Ethanol%,\n"); + + fclose(fp); +*/ + t.start(); + + while (1) { + +// char c = loggerSerial.getc(); + //temporary call function using keyboard - in future will trigger automatically. +// if ((c == 'a')) +// { + //DigoleSerialDisp.printf(" "); //print space for data output format + //poll serial device for data stream (a,0,6) to (request, return, confirm) + megasquirt.putc(97);//send 97 for run parameters, 83 for board revision, 81 code for revision number + wait(0.005); + megasquirt.putc(0); + wait(0.005); + megasquirt.putc(6); + int actuallyRead = megasquirt.readBytes( buf, 112); // where 112 is the number of bytes you are expecting + + +//decodeMS(); + + Time = t.read(); + +//void decodeMS() { + +//get seconds + tmp = buf[0]; + tmp = tmp << 8; + SecL = tmp | buf[1]; + //MSseconds = MSseconds/256; +//get pulseWidth1 + tmp = buf[2]; + tmp = tmp << 8; + tmp = tmp | buf[3]; + PW = tmp*0.000666; + + +//get pulseWidth2 + tmp = buf[4]; + tmp = tmp << 8; + tmp = tmp | buf[5]; + PW2 = tmp*0.000666; +//get Rpm + tmp = buf[6]; + tmp = tmp << 8; + RPM = tmp | buf[7]; + +//Calculate DutyCycle + DutyCycle = (PW * (RPM / 60)) / 10; + +//Calculate DutyCycle2 + DutyCycle2 = (PW2 * (RPM / 60)) / 10; + + +//get advance + tmp = buf[8]; + tmp = tmp << 8; + tmp = tmp | buf[9]; + SparkAdv = tmp/10; +//get squirt + squirt = buf[10]; +//get engine + Engine = buf[11]; +//get AFR target - Table 1 + afrtgt1 = buf[12]*10; + +//get AFR target - Table 2 + afrtgt2 = buf[13]*10; +//get WideBand Valid1 + wbo2_en1 = buf[14]; +//get WideBand Valid2 + wbo2_en2 = buf[15]; +//get Barometer + tmp = buf[16]; + tmp = tmp << 8; + tmp = tmp | buf[17]; + barometer = tmp/10; + +//get manifold absolute pressure MAP + tmp = buf[18]; + tmp = tmp << 8; + MAP = tmp | buf[19]; + MAP = MAP/10; +//get manifold absolute temperature (MAT) + tmp = buf[20]; + tmp = tmp << 8; + MAT = tmp | buf[21]; + MAT = MAT/10; ///for Farenheit + MAT = 0.555*(MAT - 32); //for Celcius +//get coolant temperature (CLT) + tmp = buf[22]; + tmp = tmp << 8; + CLT = tmp | buf[23]; + CLT = CLT/10; + CLT = 0.555*(CLT - 32); //for Celcius +//get Throttle Position Sensor (TPS) + tmp = buf[24]; + tmp = tmp << 8; + TP = tmp | buf[25]; + TP = TP / 10; +//get BAttery Voltage + tmp = buf[26]; + tmp = tmp << 8; + vBatt = tmp | buf[27]; + vBatt = vBatt /10, +//get Realtime AFR for VE1 + tmp = buf[28]; + tmp = tmp << 8; + AFR = tmp | buf[29]; + AFR = AFR /10; +//get Realtime AFR for VE2 + tmp = buf[30]; + tmp = tmp << 8; + AFR2 = tmp | buf[31]; + AFR2 = AFR2 / 10; + + +//get Knock Threshold Value + tmp = buf[32]; + tmp = tmp << 8; + knock = tmp | buf[33]; + knock = knock /10; +//get egoCorrrection1 amount % + tmp = buf[34]; + tmp = tmp << 8; + Gego = tmp | buf[35]; +//get egoCorrrection2 amount % + tmp = buf[36]; + tmp = tmp << 8; + Gego2 = tmp | buf[37]; +//get air correction (G_air) + tmp = buf[38]; + tmp = tmp << 8; + Gair = tmp | buf[39]; +//get Warmup Enrichment + tmp = buf[40]; + tmp = tmp << 8; + Gwarmup = tmp | buf[41]; + +//get accel enrichment (ms) + tmp = buf[42]; + tmp = tmp << 8; + TPSacc = tmp | buf[43]; + TPSacc = TPSacc/10; +//get TPS based fuel cut % + tmp = buf[44]; + tmp = tmp << 8; + TPScut = tmp | buf[45]; +//get baroCorrection % + tmp = buf[46]; + tmp = tmp << 8; + Gbaro = tmp | buf[47]; +//get gammaEnrich % + tmp = buf[48]; + tmp = tmp << 8; + Gammae = tmp | buf[49]; + +//get Current VE value Table 1 + tmp = buf[50]; + tmp = tmp << 8; + veCurr1 = tmp | buf[51]; + veCurr1 = veCurr1/10; +//get Current VE value Table 2 + tmp = buf[52]; + tmp = tmp << 8; + veCurr2 = tmp | buf[53]; + veCurr2 = veCurr2/10; +//get IAC Step % + tmp = buf[54]; + tmp = tmp << 8; + IAC = tmp | buf[55]; +//get Cold Ignition Advance + tmp = buf[56]; + tmp = tmp << 8; + ColdAdv = tmp | buf[57]; + ColdAdv = ColdAdv/10; +//get Rate of Change TPS + tmp = buf[58]; + tmp = tmp << 8; + tpsDOT = tmp | buf[59]; + tpsDOT = tpsDOT/10; +//get Rate of Change MAP + tmp = buf[60]; + tmp = tmp << 8; + mapDOT = tmp | buf[67]; +//get Ignition Dwell + tmp = buf[62]; + tmp = tmp << 8; + Dwell = tmp | buf[63]; + Dwell = Dwell*0.6666; +//get MAF - Mass Air Flow + tmp = buf[64]; + tmp = tmp << 8; + maf = tmp | buf[65]; +//get MAP/TPS Blend % + tmp = buf[66]; + tmp = tmp << 8; + fuelload = tmp | buf[67]; + fuelload = fuelload/10; +//get fuel load percent alchohol + tmp = buf[68]; + tmp = tmp << 8; + Ethanol = tmp | buf[69]; + +//get Spare Port Status + portstatus = buf[70]; +//get Knock timing retard (deg) + knockRetard = buf[71]; + knockRetard = knockRetard/10; +//get EAE Fuel correction + tmp = buf[72]; + tmp = tmp << 8; + EAEFuelCorr = tmp | buf[73]; + +//get egoV + tmp = buf[74]; + tmp = tmp << 8; + egoV = tmp | buf[75]; + egoV = egoV/100; +//get egoV2 + tmp = buf[76]; + tmp = tmp << 8; + egoV2 = tmp | buf[77]; + egoV2 = egoV2/100; +//get Status1 + status1 = buf[78]; +//get Status2 + status2 = buf[79]; +//get Status3 + status3 = buf[80]; +//get Status4 + status4 = buf[81]; +//get looptime + tmp = buf[82]; + tmp = tmp << 8; + looptime = tmp | buf[83]; + looptime = looptime*0.6667; +//get Status5 + status5 = buf[84]; +//get tpsADC + tmp = buf[85]; + tmp = tmp << 8; + tpsADC = tmp | buf[86]; +//get fuelload2 + tmp = buf[87]; + tmp = tmp << 8; + fuelload2 = tmp | buf[88]; +//get ignload + tmp = buf[89]; + tmp = tmp << 8; + ignload = tmp | buf[90]; + ignload = ignload/100; +//get ignload2 + tmp = buf[91]; + tmp = tmp << 8; + ignload2 = tmp | buf[92]; + ignload2 = ignload2/100; +//get Sync-Status (0 - sync-error, 1 - syncstatus) + syncstatus = buf[104]; + +//get deltaT + tmp = buf[106]; + tmp = tmp << 8; + deltaT = tmp | buf[107]; +//get wallfuel + tmp = buf[110]; + tmp = tmp << 8; + wallfuel = tmp | buf[111]; + +///Display Parameters to DigoleSerialDisp/////////// +DigoleSerialDisp.printf("SF3\r\n"); +DigoleSerialDisp.printf("SD3\r\n");//set rotation 0=0deg,1=90deg,2=180deg,3=270deg +DigoleSerialDisp.printf("TRT");//offset Line 1 in housing + + //DigoleSerialDisp.locate(0,1); + DigoleSerialDisp.printf("TT Volt=%4.1f \r\nTRT TT AFR =%4.1f\r\n TRT TT MAT= %3.0f C\r\nTRT TT CLT= %3.0f C\r\nTRT",vBatt,AFR,MAT,CLT); + DigoleSerialDisp.printf("TRT");//next line + + //DigoleSerialDisp.locate(0,0); + //DigoleSerialDisp.printf("TT AFR =%4.1f\r\n", AFR); + //DigoleSerialDisp.printf("TRT");//next line + + + +//get manifold absolute temperature (MAT) + /* + //DigoleSerialDisp.locate(10,1); + DigoleSerialDisp.printf("TT MAT= %3.0f C\r\n", MAT); + DigoleSerialDisp.printf("TRT");//next line + +//get Clt + // CLT = 0.5555*(CLT - 32); //for Celcius + //DigoleSerialDisp.locate(10,0); + DigoleSerialDisp.printf("TT CLT= %3.0f C\r\n", CLT); + DigoleSerialDisp.printf("TRT");//next line + */ + DigoleSerialDisp.printf("CL\r");//clear screen + +/* +////////////////////////write to SD Card//////////////////////////////// + if (SDenable > 0.5) //switch enable + { + myled1 = 1; + FILE *fp = fopen("/sd/datalog.csv", "a"); + fprintf(fp, "%8.3f, %4f, %i, %4.1f, %3f, %4.1f, %4.1f, %5.1f, %5.1f, %f, %f, %f, %f, %f, %f, %f, %f, %4.1f, %f, %4.1f, %f, %f, %f, %f, %f, %f, %f, %i, \n", Time, SecL, RPM, MAP, TP, vBatt, AFR, MAT, CLT, Engine, Gego, Gair, Gwarmup, Gbaro, Gammae, TPSacc, PW, DutyCycle, PW2, DutyCycle2, SparkAdv, ColdAdv, Dwell, tpsDOT, mapDOT, IAC, deltaT, Ethanol); + fclose(fp); + } else { + myled1 = 0; + } +*/ + } +} + +//exit main loop
diff -r 000000000000 -r 7ea8f0d27a4f mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Fri Nov 27 16:32:41 2015 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/49a220cc26e0 \ No newline at end of file