4 * This file is part of BeRTOS.
6 * Bertos is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * As a special exception, you may use this file as part of a free software
21 * library without restriction. Specifically, if other files instantiate
22 * templates or use macros or inline functions from this file, or you compile
23 * this file and link it with other files to produce an executable, this
24 * file does not by itself cause the resulting executable to be covered by
25 * the GNU General Public License. This exception does not however
26 * invalidate any other reasons why the executable file might be covered by
27 * the GNU General Public License.
29 * Copyright 2010 Develer S.r.l. (http://www.develer.com/)
33 * \author Daniele Basile <asterix@develer.com>
35 * \brief Simple application that implement a log device, running on the AT91SAM7X-EK board.
37 * The main scope of this application is to show you how use the SD memory card and read and write
38 * settings and logs. Thanks the ini parser module we can read settings, stored on memory card,
39 * and change the application behaviour.
40 * Generally the application work in this way:
41 * - Try to access to SD memory card, if it is present we read the inifile
42 * - If we have read correctly from SD, we compute the value that we want log
43 * (temperature, pressure and supplay voltage)
44 * - If we have enable (from ini file) to log on the file we write the log on it.
45 * - If we have enable (from ini file) to log on the serial we write the log on it.
46 * - wait the sample_time (from ini file)
47 * - contine from beginning.
49 * Here we put the ini file that this example uses. To use it copy
50 * the folling configutation line into the file called sd_fat.ini (or see INI_FILE_NAME
51 * define if you want chande the name).
54 * # Bertos SD fat project example
56 * # Basic configurarion
62 * # Enable the logging on serial device (enable = 1, disable = 0)
64 * # Enable logging on sd file (enable = 1, disable = 0)
66 * # Period between two log in millisecond
70 * # Select serial port where log
72 * # Serial port baudrate
76 * # Default text to insert on each log line
77 * line_header = BeRTOS Log:
78 * # Use this char to separate each log field
93 #include <cfg/debug.h>
95 // Define logging setting (for cfg/log.h module).
97 #define LOG_VERBOSITY 0
99 #include <cfg/macros.h>
103 #include <drv/timer.h>
106 #include <drv/tmp123.h>
107 #include <drv/spi_dma_at91.h>
108 #include <drv/mpxx6115a.h>
113 #include <mware/ini_reader.h>
116 #include <buildrev.h>
123 * Setting structure define
125 typedef struct INISetting
128 char name[80]; ///< Name of log file
129 bool log_on_serial; ///< Enable the logging on serial device
130 bool log_on_file; ///< Enable logging on sd file
131 mtime_t sample_time; ///< Period between two log (millisecond)
133 //INI serial log section
134 int port; ///< Select serial port where log
135 int baud; ///< Serial port baudrate
137 // INI log format section
138 char line_header[80]; ///< Default text to insert on each log line
139 char field_sep[10]; ///< Use this char to separate each log field
141 // INI temperature section
142 char temp_unit_label[10]; ///< Default label for measure unit
144 // INI pressure section
145 char press_unit_label[10]; ///< Default label for measure unit
147 // INI voltage section
148 char voltage_unit_label[10]; ///< Default label for measure unit
154 * Setting and various defines.
156 #define INI_FILE_NAME "sd_fat.ini" ///< Default ini file name on SD card.
159 #define LOG_SECTION "log" ///< Log section
160 #define LOG_NAME_KEY "name" ///< Name of log file
161 #define LOG_ON_SERIAL "log_on_serial" ///< Enable the logging on serial device
162 #define LOG_ON_FILE "log_on_file" ///< Enable logging on sd file
163 #define LOG_SAMPLE_TIME "sample_time" ///< Period between two log
165 //INI serial log section
166 #define SERIAL_LOG "serial_log" ///< Serial log section
167 #define SERIAL_PORT "port" ///< Select serial port where log
168 #define SERIAL_BAUD "baud" ///< Serial port baudrate
170 // INI log format section
171 #define LOG_FORMAT_SEC "log_format" ///< log format section
172 #define FORMAT_LINE_HEADER "line_header" ///< Default text to insert on each log line
173 #define FORMAT_FIELD_SEP "field_sep" ///< Use this char to separate each log field
175 // INI temperature section
176 #define TEMPERATURE "temperature" ///< temperarute section
177 #define TEMP_UNIT_LABEL "unit_label" ///< Default label for measure unit
179 // INI pressure section
180 #define PRESSURE "pressure" ///< pressure section
181 #define PRESS_UNIT_LABEL "unit_label" ///< Default label for measure unit
183 // INI voltsge section
184 #define VOLTAGE "voltage" ///< voltage section
185 #define VOLTAGE_UNIT_LABEL "unit_label" ///< Default label for measure unit
188 * Voltage reference in volts for ADC.
189 * \note This value should be complied to jumper J13 on AT91SAM7X-EK board, and
190 * the supply voltade for sensor.
191 * See schamatics for more info.
193 #define ADC_VOLTAGE_REF 3300
195 * Channel where the sensor we connect it (AD6)
196 * See schamatics for more info.
198 #define PRESSURE_SENSOR_CH 6
201 * ADC channle to read voltage supplay
202 * \note we connect board power supplay (+3.3V) to AD3 port with wire.
204 #define SUPPLAY_VOLTAGE_CH 3
205 #define ADC_SUPPLAY_VOLTAGE 3300
208 * Static definition for application devices.
210 static SpiDmaAt91 spi_dma;
211 static Serial temp_sensor_bus;
212 static Serial log_port;
215 static void init(void)
221 LOG_INFO("TIMER init..ok\n");
224 * Init temperature sensor device.
225 * - init the temperature driver
226 * - init the spi communication channel
229 // Init SPI connected to sensor temperature
230 spimaster_init(&temp_sensor_bus, SER_SPI1);
231 ser_setbaudrate(&temp_sensor_bus, 1000000L);
232 LOG_INFO("TMP123 sensor init..ok\n");
234 // Init SPI bus to communicate to SD card
235 spi_dma_init(&spi_dma);
236 spi_dma_setclock(20000000L);
237 LOG_INFO("SD SPI init..ok\n");
240 LOG_INFO("ADC init..ok\n");
246 // SD fat filesystem context
249 // Context files that we would manage
255 LOG_INFO("SD fat example project %s: %d times\n", VERS_HOST, VERS_BUILD);
264 memset(&ini_set, 0, sizeof(ini_set));
266 sd_ok = sd_init(&sd, &spi_dma.fd, 0);
270 LOG_INFO("Mount FAT filesystem.\n");
271 if ((result = f_mount(0, &fs)) != FR_OK)
273 LOG_ERR("Mounting FAT volumes error[%d]\n", result);
277 LOG_INFO("Read setting from ini file: %s\n", INI_FILE_NAME);
278 if (sd_ok && ((result = fatfile_open(&ini_file, INI_FILE_NAME, FA_READ)) != FR_OK))
280 LOG_ERR("Could not open ini file: %s error[%d,]\n", INI_FILE_NAME, result);
287 * If sd is ok, we read all setting from INI file.
288 * NOTE: if one ini key or section was not found into INI
289 * file, the iniparser return the defaul value.
291 ini_getString(&ini_file.fd, LOG_SECTION, LOG_NAME_KEY, "default.log", ini_set.name, sizeof(ini_set.name));
292 LOG_INFO("Log file name [%s]\n", ini_set.name);
295 ini_getString(&ini_file.fd, LOG_SECTION, LOG_ON_SERIAL, "1", tmp, sizeof(tmp));
296 ini_set.log_on_serial = atoi(tmp);
297 LOG_INFO("Log serial [%d]\n", ini_set.log_on_serial);
298 ini_getString(&ini_file.fd, LOG_SECTION, LOG_ON_FILE, "1", tmp, sizeof(tmp));
299 ini_set.log_on_file = atoi(tmp);
300 LOG_INFO("Log sd [%d]\n", ini_set.log_on_file);
301 ini_getString(&ini_file.fd, LOG_SECTION, LOG_SAMPLE_TIME, "500", tmp, sizeof(tmp));
302 ini_set.sample_time = atoi(tmp);
303 LOG_INFO("Sample time [%ld]\n", ini_set.sample_time);
305 ini_getString(&ini_file.fd, SERIAL_LOG, SERIAL_PORT, "0", tmp, sizeof(tmp));
306 ini_set.port = atoi(tmp);
307 LOG_INFO("Serial port [%d]\n", ini_set.port);
308 ini_getString(&ini_file.fd, SERIAL_LOG, SERIAL_BAUD, "115200", tmp, sizeof(tmp));
309 ini_set.baud = atoi(tmp);
310 LOG_INFO("Serial buad [%d]\n", ini_set.baud);
312 ini_getString(&ini_file.fd, LOG_FORMAT_SEC, FORMAT_LINE_HEADER, "BeRTOS: ", ini_set.line_header, sizeof(ini_set.line_header));
313 LOG_INFO("Serial line header[%s]\n", ini_set.line_header);
315 ini_getString(&ini_file.fd, LOG_FORMAT_SEC, FORMAT_FIELD_SEP, ",", ini_set.field_sep, sizeof(ini_set.field_sep));
316 LOG_INFO("Serial char sep[%s]\n", ini_set.field_sep);
318 ini_getString(&ini_file.fd, TEMPERATURE, TEMP_UNIT_LABEL, "C", ini_set.temp_unit_label, sizeof(ini_set.temp_unit_label));
319 LOG_INFO("Temp unit label[%s]\n", ini_set.temp_unit_label);
321 ini_getString(&ini_file.fd, PRESSURE, PRESS_UNIT_LABEL, "hPa", ini_set.press_unit_label, sizeof(ini_set.press_unit_label));
322 LOG_INFO("Press unit label[%s]\n", ini_set.press_unit_label);
324 ini_getString(&ini_file.fd, VOLTAGE, VOLTAGE_UNIT_LABEL, "V", ini_set.voltage_unit_label, sizeof(ini_set.voltage_unit_label));
325 LOG_INFO("Press unit label[%s]\n", ini_set.voltage_unit_label);
330 if (ini_set.log_on_serial)
332 // Init serial log port
333 ser_init(&log_port, ini_set.port);
334 ser_setbaudrate(&log_port, ini_set.baud);
335 LOG_INFO("SERIAL init..port[%d] buad[%d]\n", ini_set.port, ini_set.baud);
338 char log_string[160];
339 memset(log_string, 0, sizeof(log_string));
342 uint16_t vdd = ADC_RANGECONV(adc_read(SUPPLAY_VOLTAGE_CH), 0, ADC_SUPPLAY_VOLTAGE);
345 int16_t tmp = tmp123_read(&temp_sensor_bus.fd);
348 uint16_t vout = ADC_RANGECONV(adc_read(PRESSURE_SENSOR_CH), 0, vdd);
349 int16_t press = mpxx6115a_press(vout, vdd);
352 * Format string whit read data
353 * line_header + temp + temp_unit_label + field_sep + press + press_unit_label + field_sep + vdd + voltage_unit_label
355 int wr_len = sprintf(log_string, "%s%d.%01d%s%s%d%s%s%d.%d%s\r\n", ini_set.line_header,
356 tmp / 10, ABS(tmp % 10),
357 ini_set.temp_unit_label,
360 ini_set.press_unit_label,
362 vdd / 1000, ABS(vdd % 1000),
363 ini_set.voltage_unit_label);
367 * if SD is ok, try to open log file and write our data and, only
368 * if by configuration we have enable the log on file
370 if (sd_ok && ini_set.log_on_file)
372 // Open log file and do not overwrite the previous log file
373 result = fatfile_open(&log_file, ini_set.name, FA_OPEN_EXISTING | FA_WRITE);
375 // If the log file there isn't we create the new one
376 if (result == FR_NO_FILE)
378 result = fatfile_open(&log_file, ini_set.name, FA_CREATE_NEW | FA_WRITE);
379 LOG_INFO("Create the log file: %s\n", ini_set.name);
382 if ( result == FR_OK)
384 LOG_INFO("Opened log file '%s' size %ld\n", ini_set.name, log_file.fat_file.fsize);
386 // To append data we should go to end of file before to start to write
387 kfile_seek(&log_file.fd, 0, KSM_SEEK_END);
389 int len = kfile_write(&log_file.fd, log_string, wr_len);
391 // Flush data and close the files.
392 kfile_flush(&log_file.fd);
393 kfile_close(&log_file.fd);
395 // Unmount always to prevent accidental sd remove.
397 LOG_INFO("Wrote [%d]\n", len);
401 LOG_ERR("Unable to open file: '%s' error[%d]\n", ini_set.name, result);
405 // If by configuration we have enable the log on serial, we log it
406 if (ini_set.log_on_serial)
407 kfile_write(&log_port.fd, log_string, wr_len);
409 timer_delay(ini_set.sample_time);