StarBoard Orange - Example application No.1 GoogleChartLogger with StarBoard Orange
Dependencies: EthernetNetIf mbed
Revision 0:77d8b45a8f42, committed 2010-08-11
- Comitter:
- shintamainjp
- Date:
- Wed Aug 11 01:53:35 2010 +0000
- Child:
- 1:123eff9ba7b2
- Commit message:
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/EthernetNetIf.lib Wed Aug 11 01:53:35 2010 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/donatien/code/EthernetNetIf/#bc7df6da7589
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FATFileSystem.lib Wed Aug 11 01:53:35 2010 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_unsupported/code/fatfilesystem/ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GoogleChart/Axis.cpp Wed Aug 11 01:53:35 2010 +0000 @@ -0,0 +1,40 @@ +/** + * GoogleChart API interface driver. (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#include "Axis.h" + +Axis::Axis(int number, Type type) : number(number), type(type), rangeStart(0), rangeEnd(100) {} + +Axis::~Axis() {} + +int Axis::getNumber() const { + return number; +} + +void Axis::setType(Axis::Type type) { + Axis::type = type; +} + +Axis::Type Axis::getType() const { + return type; +} + +void Axis::setRangeStart(int rangeStart) { + Axis::rangeStart = rangeStart; +} + +int Axis::getRangeStart() const { + return rangeStart; +} + +void Axis::setRangeEnd(int rangeEnd) { + Axis::rangeEnd = rangeEnd; +} + +int Axis::getRangeEnd() const { + return rangeEnd; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GoogleChart/Axis.h Wed Aug 11 01:53:35 2010 +0000 @@ -0,0 +1,39 @@ +/** + * GoogleChart API interface driver. (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#ifndef _AXIS_H_ +#define _AXIS_H_ + +class Axis { +public: + typedef enum { + Bottom, + Left, + Right, + Top + } Type; + + Axis(int number, Type type = Bottom); + ~Axis(); + + int getNumber() const; + void setType(Type type); + Type getType() const; + void setRangeStart(int rangeStart); + int getRangeStart() const; + void setRangeEnd(int rangeEnd); + int getRangeEnd() const; + +private: + + const int number; + Type type; + int rangeStart; + int rangeEnd; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GoogleChart/DataSet.cpp Wed Aug 11 01:53:35 2010 +0000 @@ -0,0 +1,54 @@ +/** + * GoogleChart API interface driver. (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#include "DataSet.h" + +DataSet::DataSet(std::string label, int number, int size, DataSet::EncodeType encodeType) + : + label(label), number(number), size(size), encodeType(encodeType), dataCount(0), min(0), max(100) { + datalist = new double[size]; +} + +DataSet::~DataSet() { + delete [] datalist; +} + +std::string DataSet::getLabel() { + return label; +} + +int DataSet::getNumber() { + return number; +} + +int DataSet::getSize() { + return size; +} + +void DataSet::setEncodeType(DataSet::EncodeType encodeType) { + DataSet::encodeType = encodeType; +} + +DataSet::EncodeType DataSet::getEncodeType() { + return encodeType; +} + +void DataSet::clearAllData() { + dataCount = 0; +} + +void DataSet::addData(double data) { + datalist[dataCount++] = data; +} + +int DataSet::getDataCount() { + return dataCount; +} + +double DataSet::getData(int index) { + return datalist[index]; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GoogleChart/DataSet.h Wed Aug 11 01:53:35 2010 +0000 @@ -0,0 +1,54 @@ +/** + * GoogleChart API interface driver. (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#ifndef _DATA_SET_H_ +#define _DATA_SET_H_ + +#include <string> + +class DataSet { +public: + typedef enum { + Simple, + Extended, + Text + } EncodeType; + + DataSet(std::string label, int number, int size, EncodeType encodeType = Text); + ~DataSet(); + + std::string getLabel(); + int getNumber(); + int getSize(); + void setEncodeType(EncodeType encodeType); + EncodeType getEncodeType(); + + void clearAllData(); + void addData(double data); + int getDataCount(); + double getData(int index); + + void setScale(double min, double max) { + DataSet::min = min; + DataSet::max = max; + } + double getMin() { return min; } + double getMax() { return max; } + +private: + + const std::string label; + const int number; + const int size; + EncodeType encodeType; + double *datalist; + int dataCount; + double min; + double max; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GoogleChart/GoogleChart.cpp Wed Aug 11 01:53:35 2010 +0000 @@ -0,0 +1,339 @@ +/** + * GoogleChart API interface driver. (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#include "GoogleChart.h" + +const std::string GoogleChart::baseURL = "http://chart.apis.google.com/chart"; + +GoogleChart::GoogleChart() : title(""), width(300), height(225) { + for (int i = 0; i < MAX_AXIS; i++) { + axislist[i] = 0; + } + for (int i = 0; i < MAX_DATA; i++) { + datalist[i] = 0; + } +} + +GoogleChart::~GoogleChart() {} + +int GoogleChart::addNewAxis(Axis::Type type) { + /* + * Search maximum number of axis. + */ + int max = 0; + for (int i = 0; i < MAX_AXIS; i++) { + if (0 != axislist[i]) { + if (axislist[i]->getNumber() > max) { + max = axislist[i]->getNumber(); + } + } + } + + /* + * Create a new axis. + */ + for (int i = 0; i < MAX_AXIS; i++) { + if (0 == axislist[i]) { + axislist[i] = new Axis(max + 1, type); + return max + 1; + } + } + return -1; +} + +int GoogleChart::setAxisType(const int number, Axis::Type type) { + for (int i = 0; i < MAX_AXIS; i++) { + if (0 != axislist[i]) { + if (axislist[i]->getNumber() == number) { + axislist[i]->setType(type); + return number; + } + } + } + return -1; +} + +int GoogleChart::setAxisRange(const int number, int rangeStart, int rangeEnd) { + for (int i = 0; i < MAX_AXIS; i++) { + if (0 != axislist[i]) { + if (axislist[i]->getNumber() == number) { + axislist[i]->setRangeStart(rangeStart); + axislist[i]->setRangeEnd(rangeEnd); + return number; + } + } + } + return -1; +} + +int GoogleChart::removeAxis(const int number) { + for (int i = 0; i < MAX_AXIS; i++) { + if (0 != axislist[i]) { + if (axislist[i]->getNumber() == number) { + delete axislist[i]; + axislist[i] = 0; + return number; + } + } + } + return -1; +} + +int GoogleChart::addNewDataSet(std::string label, const int size) { + /* + * Search maximum number of data set. + */ + int max = 0; + for (int i = 0; i < MAX_DATA; i++) { + if (0 != datalist[i]) { + if (datalist[i]->getNumber() > max) { + max = datalist[i]->getNumber(); + } + } + } + + /* + * Create a new data set. + */ + for (int i = 0; i < MAX_DATA; i++) { + if (0 == datalist[i]) { + datalist[i] = new DataSet(label, max + 1, size); + return max + 1; + } + } + return -1; +} + +int GoogleChart::removeDataSet(const int number) { + for (int i = 0; i < MAX_DATA; i++) { + if (0 != datalist[i]) { + if (datalist[i]->getNumber() == number) { + delete datalist[i]; + datalist[i] = 0; + return number; + } + } + } + return -1; +} + +int GoogleChart::addData(const int number, double data) { + for (int i = 0; i < MAX_DATA; i++) { + if (0 != datalist[i]) { + if (datalist[i]->getNumber() == number) { + datalist[i]->addData(data); + return i; + } + } + } + return -1; +} + +int GoogleChart::clearAllData(const int number) { + for (int i = 0; i < MAX_DATA; i++) { + if (0 != datalist[i]) { + if (datalist[i]->getNumber() == number) { + datalist[i]->clearAllData(); + return i; + } + } + } + return -1; +} + + int GoogleChart::setDataScale(const int number, int min, int max) { + for (int i = 0; i < MAX_DATA; i++) { + if (0 != datalist[i]) { + if (datalist[i]->getNumber() == number) { + datalist[i]->setScale(min, max); + return i; + } + } + } + return -1; + } + +void GoogleChart::setTitle(std::string title) { + GoogleChart::title = title; +} + +std::string GoogleChart::getTitle() const { + return title; +} + +void GoogleChart::setWidth(int width) { + GoogleChart::width = width; +} + +int GoogleChart::getWidth() const { + return width; +} + +void GoogleChart::setHeight(int height) { + GoogleChart::height = height; +} + +int GoogleChart::getHeight() const { + return height; +} + +std::string GoogleChart::toURL(std::string text) { + static const char *unsafe_characters = " \"<>#%{}|\\^~[]`"; + std::string s = ""; + for (int i = 0; i < text.length(); i++) { + char c = text.at(i); + if (strchr(unsafe_characters, c) == NULL) { + s = s + c; + } else { + char buf[8]; + snprintf(buf, sizeof(buf), "%%%02X", c & 0xff); + s = s + std::string(buf); + } + } + return s; +} + +std::string GoogleChart::paramChartType(ChartType chartType) { + /* + * Chart Type. + */ + std::string s = "cht="; + switch (chartType) { + case LineChart: + s = s + "lc"; + break; + default: + s = s + "unknown"; + break; + } + return s; +} + +std::string GoogleChart::paramAxis(Axis **list, int size) { + + char buf[64]; + /* + * Axis type and range. + */ + int cnt = 0; + std::string sType = "chxt="; + std::string sRange = "chxr="; + for (int i = 0; i < size; i++) { + Axis *p = list[i]; + if (0 != p) { + /* + * Type. + */ + if (0 < cnt) { + sType = sType + ","; + } + switch (p->getType()) { + case Axis::Bottom: + sType = sType + "x"; + break; + case Axis::Left: + sType = sType + "y"; + break; + case Axis::Right: + sType = sType + "r"; + break; + case Axis::Top: + sType = sType + "t"; + break; + default: + sType = sType + "?"; + break; + } + /* + * Range. + */ + if (0 < cnt) { + sRange = sRange + "|"; + } + snprintf(buf, sizeof(buf), "%d,%d,%d", cnt, p->getRangeStart(), p->getRangeEnd()); + sRange = sRange + std::string(buf); + /* + * Next. + */ + cnt++; + } + } + + return sRange + "&" + sType; +} + +std::string GoogleChart::paramDataSet(DataSet **list, int size) { + char buf[64]; + int cnt = 0; + std::string sData = "chd=t:"; + std::string sScale = "chds="; + std::string sLabel = "chdl="; + for (int i = 0; i < size; i++) { + DataSet *p = list[i]; + if (0 != p) { + /* + * Data. + */ + if (0 < cnt) { + sData = sData + "|"; + } + for (int i = 0; i < p->getDataCount(); i++) { + double d = p->getData(i); + snprintf(buf, sizeof(buf), "%.3f", d); + if (0 < i) { + sData = sData + ","; + } + sData = sData + std::string(buf); + } + /* + * Range. + */ + if (0 < cnt) { + sScale = sScale + ","; + } + snprintf(buf, sizeof(buf), "%.3f,%.3f", p->getMin(), p->getMax()); + sScale = sScale + std::string(buf); + /* + * Label. + */ + if (0 < cnt) { + sLabel = sLabel + "|"; + } + sLabel = sLabel + p->getLabel(); + /* + * Next. + */ + cnt++; + } + } + + return sScale + "&" + sData + "&" + sLabel; +} + +std::string GoogleChart::paramTitle(std::string title, int color, double fontSize) { + char buf[64]; + std::string s = ""; + /* + * Chart Title Text. + */ + s = s + "chtt=" + title; + /* + * Chart Title Specification. + */ + snprintf(buf, sizeof(buf), "&chts=%06X,%.1f", color, fontSize); + s = s + std::string(buf); + return s; +} + +std::string GoogleChart::paramSize(int width, int height) { + char buf[64]; + /* + * Chart Size. + */ + snprintf(buf, sizeof(buf), "chs=%dx%d", width, height); + return std::string(buf); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GoogleChart/GoogleChart.h Wed Aug 11 01:53:35 2010 +0000 @@ -0,0 +1,71 @@ +/** + * GoogleChart API interface driver. (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#ifndef _GOOGLE_CHART_H_ +#define _GOOGLE_CHART_H_ + +#include <string.h> +#include <string> +#include <ctype.h> + +#include <mbed.h> + +#include "Axis.h" +#include "DataSet.h" + +class GoogleChart { +public: + + GoogleChart(); + virtual ~GoogleChart(); + + virtual std::string toString() = 0; + + int addNewAxis(Axis::Type type = Axis::Bottom); + int setAxisType(const int number, Axis::Type type); + int setAxisRange(const int number, int rangeStart, int rangeEnd); + int removeAxis(const int number); + + int addNewDataSet(std::string label, const int size); + int removeDataSet(const int number); + int addData(const int number, double data); + int clearAllData(const int number); + int setDataScale(const int number, int min, int max); + + void setTitle(std::string title); + std::string getTitle() const; + void setWidth(int width); + int getWidth() const; + void setHeight(int height); + int getHeight() const; + +protected: + static const std::string baseURL; + std::string title; + int width; + int height; + + static const int MAX_AXIS = 16; + Axis *axislist[MAX_AXIS]; + + static const int MAX_DATA = 16; + DataSet *datalist[MAX_DATA]; + + typedef enum { + LineChart + } ChartType; + + static std::string toURL(std::string text); + + static std::string paramChartType(ChartType chartType); + static std::string paramAxis(Axis **list, int size); + static std::string paramDataSet(DataSet **list, int size); + static std::string paramTitle(std::string title, int color, double fontSize); + static std::string paramSize(int width, int height); +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GoogleChart/GoogleChartLineChart.cpp Wed Aug 11 01:53:35 2010 +0000 @@ -0,0 +1,34 @@ +/** + * GoogleChart API interface driver. (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#include "GoogleChartLineChart.h" + +GoogleChartLineChart::GoogleChartLineChart() : GoogleChart() {} +GoogleChartLineChart::~GoogleChartLineChart() {} + +std::string GoogleChartLineChart::toString() { + + std::string s = ""; + s = s + baseURL; + s = s + "?"; + s = s + toURL(paramAxis(axislist, MAX_AXIS)); + s = s + "&"; + s = s + toURL(paramSize(400, 320)); + s = s + "&"; + s = s + toURL(paramChartType(GoogleChart::LineChart)); + s = s + "&"; + s = s + toURL("chco=3D7930,FF9900"); + s = s + "&"; + s = s + toURL(paramDataSet(datalist, MAX_DATA)); + s = s + "&"; + s = s + toURL(paramTitle(title, 0x0000FF, 12.0)); + s = s + "&"; + s = s + toURL("chg=5,5,1,1"); + s = s + "&"; + s = s + toURL("chm=B,3D793022,0,0,0,1|B,FF990022,1,0,0,1"); + return s; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GoogleChart/GoogleChartLineChart.h Wed Aug 11 01:53:35 2010 +0000 @@ -0,0 +1,24 @@ +/** + * GoogleChart API interface driver. (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#ifndef _GOOGLE_CHART_LINE_CHART_H_ +#define _GOOGLE_CHART_LINE_CHART_H_ + +#include <stdio.h> +#include <string.h> + +#include "GoogleChart.h" + +class GoogleChartLineChart : public GoogleChart { +public: + GoogleChartLineChart(); + virtual ~GoogleChartLineChart(); + + virtual std::string toString(); +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HTTPClient.lib Wed Aug 11 01:53:35 2010 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/donatien/code/HTTPClient/#d97a4fc01c86
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Sensor/Sensor.cpp Wed Aug 11 01:53:35 2010 +0000 @@ -0,0 +1,11 @@ +/** + * Sensor interface driver. (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#include "Sensor.h" + +Sensor::Sensor() {} +Sensor::~Sensor() {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Sensor/Sensor.h Wed Aug 11 01:53:35 2010 +0000 @@ -0,0 +1,18 @@ +/** + * Sensor interface driver. (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#ifndef _SENSOR_H_ +#define _SENSOR_H_ + +class Sensor { +public: + Sensor(); + virtual ~Sensor(); + virtual double read() = 0; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Sensor/SensorLM35.cpp Wed Aug 11 01:53:35 2010 +0000 @@ -0,0 +1,17 @@ +/** + * Sensor interface driver. (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#include "SensorLM35.h" + +SensorLM35::SensorLM35(PinName pin) : analogInput(pin) {} +SensorLM35::~SensorLM35() {} +double SensorLM35::read() { + /* + * The value range of analogInput.read() is 0.0 to 1.0. + */ + return ((analogInput.read() * 3.3) * 100.0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Sensor/SensorLM35.h Wed Aug 11 01:53:35 2010 +0000 @@ -0,0 +1,24 @@ +/** + * Sensor interface driver. (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#ifndef _SENSOR_LM35_H_ +#define _SENSOR_LM35_H_ + +#include <mbed.h> + +#include "Sensor.h" + +class SensorLM35 : public Sensor { +public: + explicit SensorLM35(PinName pin); + virtual ~SensorLM35(); + virtual double read(); +private: + AnalogIn analogInput; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Sensor/SensorLM60.cpp Wed Aug 11 01:53:35 2010 +0000 @@ -0,0 +1,17 @@ +/** + * Sensor interface driver. (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#include "SensorLM60.h" + +SensorLM60::SensorLM60(PinName pin) : analogInput(pin) {} +SensorLM60::~SensorLM60() {} +double SensorLM60::read() { + /* + * The value range of analogInput.read() is 0.0 to 1.0. + */ + return ((analogInput.read() * 3.3) - 0.424) / 0.00625; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Sensor/SensorLM60.h Wed Aug 11 01:53:35 2010 +0000 @@ -0,0 +1,24 @@ +/** + * Sensor interface driver. (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#ifndef _SENSOR_LM60_H_ +#define _SENSOR_LM60_H_ + +#include <mbed.h> + +#include "Sensor.h" + +class SensorLM60 : public Sensor { +public: + explicit SensorLM60(PinName pin); + virtual ~SensorLM60(); + virtual double read(); +private: + AnalogIn analogInput; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Sensor/SensorMCP9700.cpp Wed Aug 11 01:53:35 2010 +0000 @@ -0,0 +1,17 @@ +/** + * Sensor interface driver. (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#include "SensorMCP9700.h" + +SensorMCP9700::SensorMCP9700(PinName pin) : analogInput(pin) {} +SensorMCP9700::~SensorMCP9700() {} +double SensorMCP9700::read() { + /* + * The value range of analogInput.read() is 0.0 to 1.0. + */ + return (((analogInput.read() * 3.3) - 0.5) * 100.0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Sensor/SensorMCP9700.h Wed Aug 11 01:53:35 2010 +0000 @@ -0,0 +1,24 @@ +/** + * Sensor interface driver. (Version 0.0.1) + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#ifndef _SENSOR_MCP9700_H_ +#define _SENSOR_MCP9700_H_ + +#include <mbed.h> + +#include "Sensor.h" + +class SensorMCP9700 : public Sensor { +public: + explicit SensorMCP9700(PinName pin); + virtual ~SensorMCP9700(); + virtual double read(); +private: + AnalogIn analogInput; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extlib/SDFileSystem.cpp Wed Aug 11 01:53:35 2010 +0000 @@ -0,0 +1,457 @@ +/* mbed SDFileSystem Library, for providing file access to SD cards + * Copyright (c) 2008-2010, sford + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/* Introduction + * ------------ + * SD and MMC cards support a number of interfaces, but common to them all + * is one based on SPI. This is the one I'm implmenting because it means + * it is much more portable even though not so performant, and we already + * have the mbed SPI Interface! + * + * The main reference I'm using is Chapter 7, "SPI Mode" of: + * http://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf + * + * SPI Startup + * ----------- + * The SD card powers up in SD mode. The SPI interface mode is selected by + * asserting CS low and sending the reset command (CMD0). The card will + * respond with a (R1) response. + * + * CMD8 is optionally sent to determine the voltage range supported, and + * indirectly determine whether it is a version 1.x SD/non-SD card or + * version 2.x. I'll just ignore this for now. + * + * ACMD41 is repeatedly issued to initialise the card, until "in idle" + * (bit 0) of the R1 response goes to '0', indicating it is initialised. + * + * You should also indicate whether the host supports High Capicity cards, + * and check whether the card is high capacity - i'll also ignore this + * + * SPI Protocol + * ------------ + * The SD SPI protocol is based on transactions made up of 8-bit words, with + * the host starting every bus transaction by asserting the CS signal low. The + * card always responds to commands, data blocks and errors. + * + * The protocol supports a CRC, but by default it is off (except for the + * first reset CMD0, where the CRC can just be pre-calculated, and CMD8) + * I'll leave the CRC off I think! + * + * Standard capacity cards have variable data block sizes, whereas High + * Capacity cards fix the size of data block to 512 bytes. I'll therefore + * just always use the Standard Capacity cards with a block size of 512 bytes. + * This is set with CMD16. + * + * You can read and write single blocks (CMD17, CMD25) or multiple blocks + * (CMD18, CMD25). For simplicity, I'll just use single block accesses. When + * the card gets a read command, it responds with a response token, and then + * a data token or an error. + * + * SPI Command Format + * ------------------ + * Commands are 6-bytes long, containing the command, 32-bit argument, and CRC. + * + * +---------------+------------+------------+-----------+----------+--------------+ + * | 01 | cmd[5:0] | arg[31:24] | arg[23:16] | arg[15:8] | arg[7:0] | crc[6:0] | 1 | + * +---------------+------------+------------+-----------+----------+--------------+ + * + * As I'm not using CRC, I can fix that byte to what is needed for CMD0 (0x95) + * + * All Application Specific commands shall be preceded with APP_CMD (CMD55). + * + * SPI Response Format + * ------------------- + * The main response format (R1) is a status byte (normally zero). Key flags: + * idle - 1 if the card is in an idle state/initialising + * cmd - 1 if an illegal command code was detected + * + * +-------------------------------------------------+ + * R1 | 0 | arg | addr | seq | crc | cmd | erase | idle | + * +-------------------------------------------------+ + * + * R1b is the same, except it is followed by a busy signal (zeros) until + * the first non-zero byte when it is ready again. + * + * Data Response Token + * ------------------- + * Every data block written to the card is acknowledged by a byte + * response token + * + * +----------------------+ + * | xxx | 0 | status | 1 | + * +----------------------+ + * 010 - OK! + * 101 - CRC Error + * 110 - Write Error + * + * Single Block Read and Write + * --------------------------- + * + * Block transfers have a byte header, followed by the data, followed + * by a 16-bit CRC. In our case, the data will always be 512 bytes. + * + * +------+---------+---------+- - - -+---------+-----------+----------+ + * | 0xFE | data[0] | data[1] | | data[n] | crc[15:8] | crc[7:0] | + * +------+---------+---------+- - - -+---------+-----------+----------+ + */ + +#include "SDFileSystem.h" + +#define SD_COMMAND_TIMEOUT 5000 + +SDFileSystem::SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name) : + FATFileSystem(name), _spi(mosi, miso, sclk), _cs(cs) { + _cs = 1; +} + +#define R1_IDLE_STATE (1 << 0) +#define R1_ERASE_RESET (1 << 1) +#define R1_ILLEGAL_COMMAND (1 << 2) +#define R1_COM_CRC_ERROR (1 << 3) +#define R1_ERASE_SEQUENCE_ERROR (1 << 4) +#define R1_ADDRESS_ERROR (1 << 5) +#define R1_PARAMETER_ERROR (1 << 6) + +// Types +// - v1.x Standard Capacity +// - v2.x Standard Capacity +// - v2.x High Capacity +// - Not recognised as an SD Card + +#define SDCARD_FAIL 0 +#define SDCARD_V1 1 +#define SDCARD_V2 2 +#define SDCARD_V2HC 3 + +int SDFileSystem::initialise_card() { + // Set to 100kHz for initialisation, and clock card with cs = 1 + _spi.frequency(100000); + _cs = 1; + for(int i=0; i<16; i++) { + _spi.write(0xFF); + } + + // send CMD0, should return with all zeros except IDLE STATE set (bit 0) + if(_cmd(0, 0) != R1_IDLE_STATE) { + fprintf(stderr, "No disk, or could not put SD card in to SPI idle state\n"); + return SDCARD_FAIL; + } + + // send CMD8 to determine whther it is ver 2.x + int r = _cmd8(); + if(r == R1_IDLE_STATE) { + return initialise_card_v2(); + } else if(r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) { + return initialise_card_v1(); + } else { + fprintf(stderr, "Not in idle state after sending CMD8 (not an SD card?)\n"); + return SDCARD_FAIL; + } +} + +int SDFileSystem::initialise_card_v1() { + for(int i=0; i<SD_COMMAND_TIMEOUT; i++) { + _cmd(55, 0); + if(_cmd(41, 0) == 0) { + return SDCARD_V1; + } + } + + fprintf(stderr, "Timeout waiting for v1.x card\n"); + return SDCARD_FAIL; +} + +int SDFileSystem::initialise_card_v2() { + + for(int i=0; i<SD_COMMAND_TIMEOUT; i++) { + _cmd(55, 0); + if(_cmd(41, 0) == 0) { + _cmd58(); + return SDCARD_V2; + } + } + + fprintf(stderr, "Timeout waiting for v2.x card\n"); + return SDCARD_FAIL; +} + +int SDFileSystem::disk_initialize() { + + int i = initialise_card(); +// printf("init card = %d\n", i); +// printf("OK\n"); + + _sectors = _sd_sectors(); + + // Set block length to 512 (CMD16) + if(_cmd(16, 512) != 0) { + fprintf(stderr, "Set 512-byte block timed out\n"); + return 1; + } + + _spi.frequency(1000000); // Set to 1MHz for data transfer + return 0; +} + +int SDFileSystem::disk_write(const char *buffer, int block_number) { + // set write address for single block (CMD24) + if(_cmd(24, block_number * 512) != 0) { + return 1; + } + + // send the data block + _write(buffer, 512); + return 0; +} + +int SDFileSystem::disk_read(char *buffer, int block_number) { + // set read address for single block (CMD17) + if(_cmd(17, block_number * 512) != 0) { + return 1; + } + + // receive the data + _read(buffer, 512); + return 0; +} + +int SDFileSystem::disk_status() { return 0; } +int SDFileSystem::disk_sync() { return 0; } +int SDFileSystem::disk_sectors() { return _sectors; } + +// PRIVATE FUNCTIONS + +int SDFileSystem::_cmd(int cmd, int arg) { + _cs = 0; + + // send a command + _spi.write(0x40 | cmd); + _spi.write(arg >> 24); + _spi.write(arg >> 16); + _spi.write(arg >> 8); + _spi.write(arg >> 0); + _spi.write(0x95); + + // wait for the repsonse (response[7] == 0) + for(int i=0; i<SD_COMMAND_TIMEOUT; i++) { + int response = _spi.write(0xFF); + if(!(response & 0x80)) { + _cs = 1; + _spi.write(0xFF); + return response; + } + } + _cs = 1; + _spi.write(0xFF); + return -1; // timeout +} +int SDFileSystem::_cmdx(int cmd, int arg) { + _cs = 0; + + // send a command + _spi.write(0x40 | cmd); + _spi.write(arg >> 24); + _spi.write(arg >> 16); + _spi.write(arg >> 8); + _spi.write(arg >> 0); + _spi.write(0x95); + + // wait for the repsonse (response[7] == 0) + for(int i=0; i<SD_COMMAND_TIMEOUT; i++) { + int response = _spi.write(0xFF); + if(!(response & 0x80)) { + return response; + } + } + _cs = 1; + _spi.write(0xFF); + return -1; // timeout +} + + +int SDFileSystem::_cmd58() { + _cs = 0; + int arg = 0; + + // send a command + _spi.write(0x40 | 58); + _spi.write(arg >> 24); + _spi.write(arg >> 16); + _spi.write(arg >> 8); + _spi.write(arg >> 0); + _spi.write(0x95); + + // wait for the repsonse (response[7] == 0) + for(int i=0; i<SD_COMMAND_TIMEOUT; i++) { + int response = _spi.write(0xFF); + if(!(response & 0x80)) { + int ocr = _spi.write(0xFF) << 24; + ocr |= _spi.write(0xFF) << 16; + ocr |= _spi.write(0xFF) << 8; + ocr |= _spi.write(0xFF) << 0; +// printf("OCR = 0x%08X\n", ocr); + _cs = 1; + _spi.write(0xFF); + return response; + } + } + _cs = 1; + _spi.write(0xFF); + return -1; // timeout +} + +int SDFileSystem::_cmd8() { + _cs = 0; + + // send a command + _spi.write(0x40 | 8); // CMD8 + _spi.write(0x00); // reserved + _spi.write(0x00); // reserved + _spi.write(0x01); // 3.3v + _spi.write(0xAA); // check pattern + _spi.write(0x87); // crc + + // wait for the repsonse (response[7] == 0) + for(int i=0; i<SD_COMMAND_TIMEOUT * 1000; i++) { + char response[5]; + response[0] = _spi.write(0xFF); + if(!(response[0] & 0x80)) { + for(int j=1; j<5; j++) { + response[i] = _spi.write(0xFF); + } + _cs = 1; + _spi.write(0xFF); + return response[0]; + } + } + _cs = 1; + _spi.write(0xFF); + return -1; // timeout +} + +int SDFileSystem::_read(char *buffer, int length) { + _cs = 0; + + // read until start byte (0xFF) + while(_spi.write(0xFF) != 0xFE); + + // read data + for(int i=0; i<length; i++) { + buffer[i] = _spi.write(0xFF); + } + _spi.write(0xFF); // checksum + _spi.write(0xFF); + + _cs = 1; + _spi.write(0xFF); + return 0; +} + +int SDFileSystem::_write(const char *buffer, int length) { + _cs = 0; + + // indicate start of block + _spi.write(0xFE); + + // write the data + for(int i=0; i<length; i++) { + _spi.write(buffer[i]); + } + + // write the checksum + _spi.write(0xFF); + _spi.write(0xFF); + + // check the repsonse token + if((_spi.write(0xFF) & 0x1F) != 0x05) { + _cs = 1; + _spi.write(0xFF); + return 1; + } + + // wait for write to finish + while(_spi.write(0xFF) == 0); + + _cs = 1; + _spi.write(0xFF); + return 0; +} + +static int ext_bits(char *data, int msb, int lsb) { + int bits = 0; + int size = 1 + msb - lsb; + for(int i=0; i<size; i++) { + int position = lsb + i; + int byte = 15 - (position >> 3); + int bit = position & 0x7; + int value = (data[byte] >> bit) & 1; + bits |= value << i; + } + return bits; +} + +int SDFileSystem::_sd_sectors() { + + // CMD9, Response R2 (R1 byte + 16-byte block read) + if(_cmdx(9, 0) != 0) { + fprintf(stderr, "Didn't get a response from the disk\n"); + return 0; + } + + char csd[16]; + if(_read(csd, 16) != 0) { + fprintf(stderr, "Couldn't read csd response from disk\n"); + return 0; + } + + // csd_structure : csd[127:126] + // c_size : csd[73:62] + // c_size_mult : csd[49:47] + // read_bl_len : csd[83:80] - the *maximum* read block length + + int csd_structure = ext_bits(csd, 127, 126); + int c_size = ext_bits(csd, 73, 62); + int c_size_mult = ext_bits(csd, 49, 47); + int read_bl_len = ext_bits(csd, 83, 80); + +// printf("CSD_STRUCT = %d\n", csd_structure); + + if(csd_structure != 0) { + fprintf(stderr, "This disk tastes funny! I only know about type 0 CSD structures\n"); + return 0; + } + + // memory capacity = BLOCKNR * BLOCK_LEN + // where + // BLOCKNR = (C_SIZE+1) * MULT + // MULT = 2^(C_SIZE_MULT+2) (C_SIZE_MULT < 8) + // BLOCK_LEN = 2^READ_BL_LEN, (READ_BL_LEN < 12) + + int block_len = 1 << read_bl_len; + int mult = 1 << (c_size_mult + 2); + int blocknr = (c_size + 1) * mult; + int capacity = blocknr * block_len; + + int blocks = capacity / 512; + + return blocks; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extlib/SDFileSystem.h Wed Aug 11 01:53:35 2010 +0000 @@ -0,0 +1,81 @@ +/* mbed SDFileSystem Library, for providing file access to SD cards + * Copyright (c) 2008-2010, sford + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MBED_SDFILESYSTEM_H +#define MBED_SDFILESYSTEM_H + +#include "mbed.h" +#include "FATFileSystem.h" + +/** Access the filesystem on an SD Card using SPI + * + * @code + * #include "mbed.h" + * #include "SDFileSystem.h" + * + * SDFileSystem sd(p5, p6, p7, p12, "sd"); // mosi, miso, sclk, cs + * + * int main() { + * FILE *fp = fopen("/sd/myfile.txt", "w"); + * fprintf(fp, "Hello World!\n"); + * fclose(fp); + * } + */ +class SDFileSystem : public FATFileSystem { +public: + + /** Create the File System for accessing an SD Card using SPI + * + * @param mosi SPI mosi pin connected to SD Card + * @param miso SPI miso pin conencted to SD Card + * @param sclk SPI sclk pin connected to SD Card + * @param cs DigitalOut pin used as SD Card chip select + * @param name The name used to access the virtual filesystem + */ + SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name); + virtual int disk_initialize(); + virtual int disk_write(const char *buffer, int block_number); + virtual int disk_read(char *buffer, int block_number); + virtual int disk_status(); + virtual int disk_sync(); + virtual int disk_sectors(); + +protected: + + int _cmd(int cmd, int arg); + int _cmdx(int cmd, int arg); + int _cmd8(); + int _cmd58(); + int initialise_card(); + int initialise_card_v1(); + int initialise_card_v2(); + + int _read(char *buffer, int length); + int _write(const char *buffer, int length); + int _sd_sectors(); + int _sectors; + + SPI _spi; + DigitalOut _cs; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extlib/TextLCD.cpp Wed Aug 11 01:53:35 2010 +0000 @@ -0,0 +1,167 @@ +/* mbed TextLCD Library, for a 4-bit LCD based on HD44780 + * Copyright (c) 2007-2010, sford + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/* + * Modified for star board orange by Shinichiro Nakamura. (CuBeatSystems) + * + * ID : shintamainjp + * Added : RW- + */ + +#include "TextLCD.h" +#include "mbed.h" + +TextLCD::TextLCD(PinName rs, PinName rw, PinName e, PinName d0, PinName d1, + PinName d2, PinName d3, LCDType type) : _rs(rs), _rw(rw), + _e(e), _d(d0, d1, d2, d3), + _type(type) { + + _e = 1; + _rs = 0; // command mode + _rw = 0; + + wait(0.015); // Wait 15ms to ensure powered up + + // send "Display Settings" 3 times (Only top nibble of 0x30 as we've got 4-bit bus) + for (int i=0; i<3; i++) { + writeByte(0x3); + wait(0.00164); // this command takes 1.64ms, so wait for it + } + writeByte(0x2); // 4-bit mode + wait(0.000040f); // most instructions take 40us + + writeCommand(0x28); // Function set 001 BW N F - - + writeCommand(0x0C); + writeCommand(0x6); // Cursor Direction and Display Shift : 0000 01 CD S (CD 0-left, 1-right S(hift) 0-no, 1-yes + cls(); +} + +void TextLCD::character(int column, int row, int c) { + int a = address(column, row); + writeCommand(a); + writeData(c); +} + +void TextLCD::cls() { + writeCommand(0x01); // cls, and set cursor to 0 + wait(0.00164f); // This command takes 1.64 ms + locate(0, 0); +} + +void TextLCD::locate(int column, int row) { + _column = column; + _row = row; +} + +int TextLCD::_putc(int value) { + if (value == '\n') { + _column = 0; + _row++; + if (_row >= rows()) { + _row = 0; + } + } else { + character(_column, _row, value); + _column++; + if (_column >= columns()) { + _column = 0; + _row++; + if (_row >= rows()) { + _row = 0; + } + } + } + return value; +} + +int TextLCD::_getc() { + return -1; +} + +void TextLCD::writeByte(int value) { + _d = value >> 4; + wait(0.000040f); // most instructions take 40us + _e = 0; + wait(0.000040f); + _e = 1; + _d = value >> 0; + wait(0.000040f); + _e = 0; + wait(0.000040f); // most instructions take 40us + _e = 1; +} + +void TextLCD::writeCommand(int command) { + _rs = 0; + writeByte(command); +} + +void TextLCD::writeData(int data) { + _rs = 1; + writeByte(data); +} + +int TextLCD::address(int column, int row) { + switch (_type) { + case LCD20x4: + switch (row) { + case 0: + return 0x80 + column; + case 1: + return 0xc0 + column; + case 2: + return 0x94 + column; + case 3: + return 0xd4 + column; + } + case LCD16x2B: + return 0x80 + (row * 40) + column; + case LCD16x2: + case LCD20x2: + default: + return 0x80 + (row * 0x40) + column; + } +} + +int TextLCD::columns() { + switch (_type) { + case LCD20x4: + case LCD20x2: + return 20; + case LCD16x2: + case LCD16x2B: + default: + return 16; + } +} + +int TextLCD::rows() { + switch (_type) { + case LCD20x4: + return 4; + case LCD16x2: + case LCD16x2B: + case LCD20x2: + default: + return 2; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extlib/TextLCD.h Wed Aug 11 01:53:35 2010 +0000 @@ -0,0 +1,119 @@ +/* mbed TextLCD Library, for a 4-bit LCD based on HD44780 + * Copyright (c) 2007-2010, sford + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/* + * Modified for star board orange by Shinichiro Nakamura. (CuBeatSystems) + * + * ID : shintamainjp + * Added : RW- + */ + +#ifndef MBED_TEXTLCD_H +#define MBED_TEXTLCD_H + +#include "mbed.h" + +/** A TextLCD interface for driving 4-bit HD44780-based LCDs + * + * Currently supports 16x2, 20x2 and 20x4 panels + * + * @code + * #include "mbed.h" + * #include "TextLCD.h" + * + * TextLCD lcd(p10, p12, p15, p16, p29, p30); // rs, e, d0-d3 + * + * int main() { + * lcd.printf("Hello World!\n"); + * } + * @endcode + */ +class TextLCD : public Stream { +public: + + /** LCD panel format */ + enum LCDType { + LCD16x2 /**< 16x2 LCD panel (default) */ + , LCD16x2B /**< 16x2 LCD panel alternate addressing */ + , LCD20x2 /**< 20x2 LCD panel */ + , LCD20x4 /**< 20x4 LCD panel */ + }; + + /** Create a TextLCD interface + * + * @param rs Instruction/data control line. + * @param rw Read/Write- control line. + * @param e Enable line (clock) + * @param d0-d3 Data lines + * @param type Sets the panel size/addressing mode (default = LCD16x2) + */ + TextLCD(PinName rs, PinName rw, PinName e, PinName d0, PinName d1, PinName d2, PinName d3, LCDType type = LCD16x2); + +#if DOXYGEN_ONLY + /** Write a character to the LCD + * + * @param c The character to write to the display + */ + int putc(int c); + + /** Write a formated string to the LCD + * + * @param format A printf-style format string, followed by the + * variables to use in formating the string. + */ + int printf(const char* format, ...); +#endif + + /** Locate to a screen column and row + * + * @param column The horizontal position from the left, indexed from 0 + * @param row The vertical position from the top, indexed from 0 + */ + void locate(int column, int row); + + /** Clear the screen and locate to 0,0 */ + void cls(); + + int rows(); + int columns(); + +protected: + + // Stream implementation functions + virtual int _putc(int value); + virtual int _getc(); + + int address(int column, int row); + void character(int column, int row, int c); + void writeByte(int value); + void writeCommand(int command); + void writeData(int data); + + DigitalOut _rs, _rw, _e; + BusOut _d; + LCDType _type; + + int _column; + int _row; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Aug 11 01:53:35 2010 +0000 @@ -0,0 +1,290 @@ +/** + * StarBoard Orange - Example application No.1 (Version 0.0.1) + * + * GoogleChartLogger with StarBoard Orange + * + * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) + * http://shinta.main.jp/ + */ + +#include "mbed.h" +#include "SDFileSystem.h" +#include "TextLCD.h" +#include "EthernetNetIf.h" +#include "HTTPClient.h" +#include "SensorLM60.h" +#include "SensorLM35.h" +#include "SensorMCP9700.h" +#include "GoogleChartLineChart.h" + +#define SUPERTWEET_ACCOUNT "YourAccount" +#define SUPERTWEET_PASSWORD "YourPassword" + +#if 1 +/* + * Use "DHCP" + */ +EthernetNetIf eth; +#else +/* + * Use "static IP address" + * + * -> IP + * -> Subnet mask + * -> Gateway + * -> DNS + */ +EthernetNetIf eth( + IpAddr(xxx,xxx,xxx,xxx), + IpAddr(xxx,xxx,xxx,xxx), + IpAddr(xxx,xxx,xxx,xxx), + IpAddr(xxx,xxx,xxx,xxx)); +#endif +TextLCD lcd(p24, p25, p26, p27, p28, p29, p30); +SDFileSystem sd(p5, p6, p7, p8, "sd"); +BusOut led(LED4, LED3, LED2, LED1); +SensorMCP9700 sensor1(p20); +SensorMCP9700 sensor2(p19); + +void splash(void); +void getDateTime(char *buf, int siz); +int main(void); + +/** + * Display a splash screen. + */ +void splash(void) { + lcd.cls(); + lcd.locate(0, 0); + lcd.printf("StarBoard Orange"); + lcd.locate(0, 1); + lcd.printf("mbed NXP LPC1768"); + wait(3); + + lcd.cls(); + lcd.locate(0, 0); + lcd.printf("Example app No.1"); + lcd.locate(0, 1); + lcd.printf("with GoogleChart"); + wait(3); +} + +/** + * Set current date and time. + * + * @param year Year. + * @param month Month. + * @param day Day. + * @param hour Hour. + * @param min Minutes. + * @param sec Seconds. + */ +void setDateTime(int year, int month, int day, int hour, int min, int sec) { + struct tm t; + t.tm_sec = sec; + t.tm_min = min; + t.tm_hour = hour; + t.tm_mday = day; + t.tm_mon = month - 1; + t.tm_year = year - 1900; + time_t seconds = mktime(&t); + set_time(seconds); +} + +/** + * Get current date and time. + * + * @param buf Pointer to buffer. + * @param siz Size of buffer. + */ +void getDateTime(char *buf, int siz) { + time_t seconds = time(NULL); + struct tm *t = localtime(&seconds); + strftime(buf, siz, "%b/%d/%Y %H:%M:%S", t); +} + +/** + * Entry point. + */ +int main(void) { + + /* + * Splash. + */ + splash(); + + /* + * Initialize ethernet interface. + */ + lcd.cls(); + lcd.locate(0, 0); + lcd.printf("Initializing. "); + lcd.locate(0, 1); + lcd.printf("Ethernet: "); + + EthernetErr ethErr = eth.setup(); + if (ethErr) { + lcd.locate(0, 1); + lcd.printf("Ethernet:NG "); + } else { + lcd.locate(0, 1); + lcd.printf("Ethernet:OK "); + } + wait(3); + + /* + * Check your SD card. + */ + lcd.cls(); + lcd.locate(0, 0); + lcd.printf("Checking SD card"); + lcd.locate(0, 1); + lcd.printf("SD card: "); + wait(1); + FILE *fp = fopen("/sd/log_test.txt", "w"); + if (NULL != fp) { + fprintf(fp, "This is a test file for SD card."); + fclose(fp); + lcd.locate(0, 1); + lcd.printf("SD card:OK "); + } else { + lcd.locate(0, 1); + lcd.printf("SD card:NG "); + } + wait(1); + + /* + * Setup http client object. + * + * Please replace this information by your account. + */ + HTTPClient twitter; + twitter.basicAuth(SUPERTWEET_ACCOUNT, SUPERTWEET_PASSWORD); + + /* + * Setup GoogleChart objects. + */ + static const int SAMPLES = 60; + static const int INTERVAL = 1; + + GoogleChartLineChart chart; + const int axs1 = chart.addNewAxis(Axis::Left); + const int axs2 = chart.addNewAxis(Axis::Bottom); + const int dsn1 = chart.addNewDataSet("Ch.1", SAMPLES); + const int dsn2 = chart.addNewDataSet("Ch.2", SAMPLES); + + static const int TEMP_HIGH = 50; + static const int TEMP_LOW = -10; + + chart.setAxisRange(axs1, TEMP_LOW, TEMP_HIGH); + chart.setAxisRange(axs2, 0, SAMPLES); + chart.setDataScale(dsn1, TEMP_LOW, TEMP_HIGH); + chart.setDataScale(dsn2, TEMP_LOW, TEMP_HIGH); + + + /* + * Set date and time. (If you want.) + * + * -> Year. + * -> Month. + * -> Day. + * -> Hour. + * -> Minutes. + * -> Seconds. + */ +#if 0 + setDateTime(2012, 1, 1, 0, 0, 0); +#endif + + /* + * Start logging. + */ + uint16_t count = 0; + static const int WAIT_FOR_USER = 1; + while (1) { + /* + * Get date and time + */ + if (0 == (count % SAMPLES)) { + char dt[64]; + getDateTime(dt, sizeof(dt)); + chart.setTitle(std::string(dt)); + } + count++; + + /* + * Status on LED. + */ + led = count & 0x0f; + + /* + * Logging current status. + */ + double sample1 = sensor1.read(); + double sample2 = sensor2.read(); + chart.addData(dsn1, sample1); + chart.addData(dsn2, sample2); + + /* + * Display the information. + */ + lcd.cls(); + lcd.locate(0, 0); + lcd.printf("Data=[%4.1f,%4.1f]", sample1, sample2); + lcd.locate(0, 1); + lcd.printf("Stat=[%4d/%4d]", count, SAMPLES); + + /* + * Write to storages if the data filled the chart. + */ + if (0 == (count % SAMPLES)) { + /* + * Write to a SD card. + */ + static int fcnt = 0; + fcnt++; + char fname[64]; + snprintf(fname, sizeof(fname), "/sd/log%05d.txt", fcnt); + lcd.locate(0, 1); + lcd.printf("SD card: "); + FILE *fp = fopen(fname, "w"); + if (NULL != fp) { + fprintf(fp, "%s\n", chart.toString().c_str()); + fclose(fp); + lcd.locate(0, 1); + lcd.printf("SD card:OK "); + } else { + lcd.locate(0, 1); + lcd.printf("SD card:NG "); + } + wait(WAIT_FOR_USER); + + /* + * Write to twitter. + */ + lcd.locate(0, 1); + lcd.printf("Tweet: "); + HTTPMap msg; + msg["status"] = chart.toString(); + HTTPResult r = twitter.post("http://api.supertweet.net/1/statuses/update.xml", msg, NULL); + if (r == HTTP_OK) { + lcd.locate(0, 1); + lcd.printf("Tweet:OK "); + } else { + lcd.locate(0, 1); + lcd.printf("Tweet:NG(%02d) ", r); + } + wait(WAIT_FOR_USER); + + /* + * Clear the logged data. + */ + chart.clearAllData(dsn1); + chart.clearAllData(dsn2); + count = 0; + } + wait(INTERVAL); + } + + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Wed Aug 11 01:53:35 2010 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/9114680c05da