rustmatic icon indicating copy to clipboard operation
rustmatic copied to clipboard

Implement IEC RTC function block

Open NOP0 opened this issue 5 years ago • 5 comments

This is a function block from the standard. I think we'll need this for the blinky IEC program, since this is analog to elapsed?

The interface is like this:

FUNCTION_BLOCK RTC // Real Time Clock

VAR_INPUT
    IN : BOOL; // Preset and run
    PDT: DT; // Preset value of RTC loaded on rising edge of IN
END_VAR

VAR_OUTPUT
    Q : BOOL; // CDT output is valid
    CDT : DT; // Current time
END_VAR

// Body unimplemented!

END_FUNCTION_BLOCK
    






NOP0 avatar Dec 17 '19 11:12 NOP0

We also need time formats. #34

NOP0 avatar Dec 17 '19 11:12 NOP0

I'm not sure how we'll implement components from the "standard library" and expose them to WASM.

I guess we'd define opaque structs and then various extern "C" fn() functions for invoking a function block. By using a C-style interface WASM code will easily be able to use exported functions.

Types like DateTime will (for the time being) probably need to be allocated at runtime and passed around via pointers because WASM only supports u32, u64, f32, and f64 as function parameters.

/// Opaque type representing a date and time. Can only be used via pointer operations.
struct DateTime { ... }

/// Create a new immutable `DateTime` object.
#[no_mangle]
pub extern "C" fn datetime_create(year: i32, month: u32, day: u32, hour: u32, min: u32, sec: u32, nanos: u32) -> *const DateTime { ... }

#[no_mangle]
pub extern "C" fn datetime_destrly(dt: *const DateTime) { ... }

#[no_mangle]
pub extern "C" fn datetime_year(dt: *const DateTime) -> i32 { ... }

struct RealtimeClock { ... }

#[no_mangle]
pub extern "C" fn realtime_clock_create() -> *mut RealtimeClock { ... }

#[no_mangle]
pub extern "C" fn realtime_clock_destroy(rtc: *mut RealtimeClock) { ... }

/// Poll the `RealtimeClock`.
#[no_mangle]
pub extern "C" fn realtime_clock_poll(rtc: *mut RealtimeClock, in_: bool, pdt: *const DateTime) -> (bool, *const DateTime) { ... }

Michael-F-Bryan avatar Dec 17 '19 17:12 Michael-F-Bryan

I think your example seems like an approach worth trying.

Types like DateTime will (for the time being) probably need to be allocated at runtime and passed around via pointers because WASM only supports u32, u64, f32, and f64 as function parameters.

For the concrete case of DateTime would an internal implementation as an u64 UNIX epoch solve anything? But on the other hand, there will be other datatypes like IEC string that will need the pointer approach, so maybe better use that throughout.

NOP0 avatar Dec 17 '19 20:12 NOP0

I guess you could do that, but using a u64 means you can't have subsecond resolution. Does the spec say whether a date-time can do fractional seconds?

Michael-F-Bryan avatar Dec 18 '19 04:12 Michael-F-Bryan

I think the spec says:

DATE_AND_TIME#1970-01-01-00:00:00.000

But the underlying storage is specified as implementation dependent.

But googling around, I see that some vendors say that they use u32 for the storage of seconds since 1970 which is epoch. So in those systems the milliseconds are just thrown away?

I guess you could store msecs since 1970 in an u64 (when would that overflow?). Then you've got time_spec and ISO, and the rust format... so timestamps are a mess IMHO.

NOP0 avatar Dec 18 '19 11:12 NOP0