Hi,
for a private microcontroller project, I use Céu for the reactive part of my application. In this context, I have to convert rtc time stamps (32 bit integers) into a date and time information (year, month, day, hour, minute, and so on). A working C code example is attached. I wanted to stay in the Céu language and hence decided to reimplement the conversion function in Céu. Since the conversion process is a one-step function which does not involve event handling, I would like to implement it using a code/tight abstraction. My first shot in Céu, which is not working yet, looks like this:
#define EPOCH_YR 2000
#define EPOCH_DOW 6
#define IS_LEAPYEAR(year) ( ((year)%400==0) or (((year)%4==0) and ((year)%100!=0)) )
#define YEARSIZE(year) do if IS_LEAPYEAR(year) then escape 366; else escape 365; end end
#define MONTHSIZE(m, isLeap) do \
if m == 0 then \
escape 31; \
else/if m == 1 then \
if isLeap then \
escape 29; \
else \
escape 28; \
end \
else/if m == 2 then \
escape 31; \
else/if m == 3 then \
escape 30; \
else/if m == 4 then \
escape 31; \
else/if m == 5 then \
escape 30; \
else/if m == 6 then \
escape 31; \
else/if m == 7 then \
escape 31; \
else/if m == 8 then \
escape 30; \
else/if m == 9 then \
escape 31; \
else/if m == 10 then \
escape 30; \
else/if m == 11 then \
escape 31; \
else \
end \
end
data TimeInformation with
var u8 second = 0;
var u8 minute = 0;
var u8 hour = 0;
var u16 day = 0;
var u8 month = 0;
var u16 year = 0;
var u8 day_of_week = 0;
end
code/tight Seconds2Time (var u32 seconds, var& TimeInformation ti) -> none do
var u16 year = EPOCH_YR;
var u16 days = (seconds / 86400) as u16;
var u32 day_seconds = seconds % 86400;
ti.second = (day_seconds % 60) as u8;
ti.minute = ((day_seconds % 3600) / 60) as u8;
ti.hour = (day_seconds / 3600) as u8;
ti.day_of_week = ((days + EPOCH_DOW) % 7) as u8;
loop do
var u16 ysize = YEARSIZE(year);
if days < ysize then break; end
days = days - ysize;
year = year + 1;
end
ti.year = year;
ti.month = 0;
var bool isLeap = IS_LEAPYEAR(ti.year);
loop do
var u8 msize = MONTHSIZE(ti.month, isLeap);
if days < msize then break; end
days = days - msize;
ti.month = ti.month + 1;
end
ti.month = ti.month + 1;
ti.day = days + 1;
end
I encountered the following difficulties during implementation:
- I did not manage to declare a multidimensional array in Céu like it is used for the _ytab in C. Consequently, I ended up with the tedious workaround
#define MONTHSIZE...
- In order to account for (1), I tried to initialize two one-dimensional vectors within the Seconds2Time function and select the required one during the loop iterations
var[12] u8 tabL = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; // leap year
var[12] u8 tabNL = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; // no leap year
var&[] u8 tab;
if <is leap year> then
tab = &tabL;
else
tab = &tabNL;
end
<use tab>
However, I got an compilation error that I cannot declare vectors in a code/tight block.
- It appears that there is no while loop in Céu which I can use to check an arbitrary condition. Consequently, I ended up with using an if statement to break the endless loop as soon as the condition is met. Additionally, the Céu compiler outputs a tight loop warning - which is reasonable since there is no upper bound to the maximum number of loop iterations.
Do you have any suggestions/hints on how to implement algorithms, like e.g. the seconds2time conversion from C, in a simple and straight forward manner in Céu? Or should I stick to C for algorithmic operations like this one and use Céu mainly for the controlling and coordinating part?
Thanks in advance!
Regards,
Matthias