Switch back to 115.2kbps
[rmslog.git] / rmslog / main.c
1 /**
2  * \file
3  *
4  * \author Bernie Innocenti <bernie@codewiz.org>
5  *
6  * \brief Serial data logger for RMS
7  *
8  * This application records all incoming data from an RS-232 serial port
9  * to a file on a FAT-formatted SD card. It can be used to log kernel
10  * console messages.
11  */
12
13 #include "hw/hw_led.h"
14
15 #define LOG_LEVEL      3
16 #include <cfg/log.h>
17 #include <cfg/debug.h>
18
19 #include <cpu/irq.h>
20 #include <cpu/power.h>
21
22 #ifdef BERTOS_FAT
23         #include <drv/sd.h>
24         #include <fs/fat.h>
25 #else
26         #include <FAT16/fat.h>
27         #include <FAT16/partition.h>
28         #include <FAT16/sd_raw.h>
29 #endif
30
31 #include <drv/ser.h>
32 #include <drv/timer.h>
33 #include <kern/proc.h>
34
35 #include <string.h>
36
37
38 static Serial ser;
39
40 #ifdef BERTOS_FAT
41         static Serial spi;
42         static FATFS fs;
43         static FatFile file;
44         static Sd sd;
45 #else
46         struct fat_fs_struct        *fs;
47         struct partition_struct     *partition;
48         struct fat_dir_struct       *dd;
49         struct fat_dir_entry_struct dir_entry;
50         struct fat_file_struct      *fd;
51 #endif
52
53
54 #ifndef BERTOS_FAT
55 static void fat_init(void)
56 {
57         partition = partition_open(
58                 sd_raw_read,
59                 sd_raw_read_interval,
60                 sd_raw_write,
61                 sd_raw_write_interval,
62                 0
63         );
64
65         if (!partition)
66         {
67                 // If the partition did not open, assume the storage device
68                 // is a "superfloppy", i.e. has no MBR.
69                 partition = partition_open(
70                         sd_raw_read,
71                         sd_raw_read_interval,
72                         sd_raw_write,
73                         sd_raw_write_interval,
74                         0
75                 );
76         }
77         if (!partition)
78         {
79                 ASSERT(0); for(;;) {}
80         }
81
82         if (!(fs = fat_open(partition)))
83         {
84                 ASSERT(0); for(;;) {}
85         }
86
87     //Open root directory
88     fat_get_dir_entry_of_path(fs, "/", &dir_entry);
89     if (!(dd = fat_open_dir(fs, &dir_entry)))
90         {
91                 ASSERT(0); for(;;) {}
92         }
93 }
94
95 static uint8_t find_file_in_dir(UNUSED_ARG(struct fat_fs_struct *, fs), struct fat_dir_struct* dd, const char* name, struct fat_dir_entry_struct* dir_entry)
96 {
97         fat_reset_dir(dd);      //Make sure to start from the beginning of the directory!
98     while(fat_read_dir(dd, dir_entry))
99     {
100         if(strcmp(dir_entry->long_name, name) == 0)
101         {
102             //fat_reset_dir(dd);
103             return 1;
104         }
105     }
106
107     return 0;
108 }
109
110 static struct fat_file_struct *open_file_in_dir(struct fat_fs_struct* fs, struct fat_dir_struct* dd, const char* name)
111 {
112     struct fat_dir_entry_struct file_entry;
113     if(!find_file_in_dir(fs, dd, name, &file_entry))
114         return 0;
115
116     return fat_open_file(fs, &file_entry);
117 }
118
119 #endif // !BERTOS_FAT
120
121 static void init(void)
122 {
123         /* Initialize debugging module (allow kprintf(), etc.) */
124         kdbg_init();
125
126         /* Initialize system timer */
127         timer_init();
128
129         /* Enable all the interrupts */
130         IRQ_ENABLE;
131
132         /* Kernel initialization: processes */
133         proc_init();
134
135         /* Initialize UART0 */
136         ser_init(&ser, SER_UART0);
137
138         //FIXME: The 16MHz arduino clock causes 3.5% baudrate error at 115200
139         //ser_setbaudrate(&ser, 115200);
140         ser_setbaudrate(&ser, 57600);
141         UCSR0A = BV(U2X0);
142
143         // At this baud rate, we're fast enought to write a continuous
144         // input stream to the SD card
145         //ser_setbaudrate(&ser, 19200);
146
147         /* Initialize LED driver */
148         LED_INIT();
149
150         timer_delay(1000);
151         kfile_printf(&ser.fd, "Hello, world!\r\n");
152
153 #ifdef BERTOS_FAT
154         ser_init(&spi, SER_SPI);
155 #else
156         DDRB |= BV(PORTB0) | BV(PORTB2) | BV(PORTB3) | BV(PORTB5);
157         if (!sd_raw_init())
158         {
159                 ASSERT(0); for(;;) {}
160         }
161 #endif
162
163         fat_init();
164 }
165
166
167 int main(void)
168 {
169         init();
170
171 #ifdef BERTOS_FAT
172
173         FRESULT fat_err;
174         if ((fat_err = f_mount(0, &fs)) != FR_OK)
175         {
176                 LOG_ERR("Error mounting FAT volume: %d\n", fat_err);
177         }
178
179         fat_err = fatfile_open(&file, "foo.txt", FA_WRITE | FA_CREATE_ALWAYS);
180         ASSERT(fat_err == FR_OK);
181
182         size_t count = kfile_write(&file.fd, "Hello, world!", strlen("Hello, world!"));
183         ASSERT(count == strlen("Hello, world!"));
184
185 #else
186
187         fat_create_file(dd, "log.txt", &dir_entry);
188         fd = open_file_in_dir(fs, dd, "log.txt");
189         int32_t offset = 0;
190         fat_seek_file(fd, &offset, FAT_SEEK_END);
191
192 #endif
193
194         while (1)
195         {
196                 size_t size;
197                 char buf[128];
198                 bool sync_pending = false;
199
200                 if ((size = ser_read(&ser, buf, sizeof(buf))) != 0)
201                 {
202                         LED_ON();
203                         fat_write_file(fd, (void *)buf, size);
204                         sync_pending = true;
205                         LED_OFF();
206                 }
207                 else
208                 {
209                         serstatus_t err = ser_getstatus(&ser);
210                         if (err & ~SERRF_RXTIMEOUT)
211                         {
212                                 LED_ON();
213                                 kfile_printf(&ser.fd, "\r\n*** err=%d ***\r\n", err);
214                         }
215                         ser_setstatus(&ser, 0);
216
217                         if (sync_pending)
218                         {
219                                 LED_ON();
220                                 sd_raw_sync();
221                                 LED_OFF();
222                                 sync_pending = false;
223                         }
224                 }
225         }
226         fat_close_file(fd);
227 }