fossasia / pslab-firmware

Firmware for PSLab Open Hardware Platform https://pslab.io
Apache License 2.0
1.56k stars 75 forks source link

Add time and date to FatFS #159

Closed bessman closed 12 months ago

bessman commented 1 year ago

Background

The PSLab v6 has a Real Time Clock which keeps track of the current time as long as it's powered. The time can be set and read over serial, via the rtc module.

The SD-card driver, FatFS, needs to be able to read the time in order to set correct timestamps when saving files. This is handled in ff_time.c, which currently contains a dummy implementation which always returns the timestamp 2018-06-31 05:10:30.

Tasks

Hrushi20 commented 1 year ago

Hey, can you give me a quick overview of UART_READ and UARD_WRITE? As per my understanding does UART1_READ reads the data from register and returns us the byte and does UARD1_WRITE writes the data to registers?

Hrushi20 commented 1 year ago

Also, DS1307 module supports BCD format. So do I take uint8_t as input and convert it to BCD format in rtc.c file?

bessman commented 1 year ago

Hey, can you give me a quick overview of UART_READ and UARD_WRITE? As per my understanding does UART1_READ reads the data from register and returns us the byte and does UARD1_WRITE writes the data to registers?

Yes, that's right. The PSLab is controlled by a host computer, with which it communicates over a serial connection. The host sends command instructions and associated data, which the PSLab receives in its UART1RX register (which the UART1_Read function reads from). The PSLab runs said command and sends back its return values by writing them to its UART1TX register (which the UART1_Write function writes to).

For the RTC, a transaction might look like this:

                    RTC_SETTIME  Time & Date
Host -----> bytes: [13, 1,       a, b, c, d, e, f, g, h] -----> PSLab

                    Return Code
Host <----- bytes: [R] <----- PSLab

Where a, b, c, e, f, g, h are bytes containing BCD-formatted time and date, per the DS1307 datasheet, and R is a return code indicating whether the command succeeded (in this case it is the return code from the I2C module, since the RTC is connected on the I2C bus).

Also, DS1307 module supports BCD format. So do I take uint8_t as input and convert it to BCD format in rtc.c file?

Good question. That's how it's currently implemented, but since this part of the protocol is new we could still change it without breaking backward compatibility. I would actually prefer to send the time to the PSLab as a 32-bit Unix timestamp and have the firmware handle the BCD conversion. You can use UART1_read_u32 to read four bytes at once from the serial bus.

(Sorry about the different naming standards for functions; we haven't really settled on a consistent style. Just follow the same style as is currently used in rtc.c)

Hrushi20 commented 1 year ago

Hey, How do we identify if the host wants 12hr or 24 hour time format. Based on the 32bit unix stamp we can't decide right? Do we have another data byte to read from which specifies what kind of time_format to be used?

Hrushi20 commented 1 year ago

Another thing I noticed is the DS1307 supports year in format [00-99]. While reading the year from DS1307 and converting it back to unix timestamp I have no way of knowing which year it belongs to.

Host:    -------> 2023  ---------> 23 -------> DS1307      (Write Operation)
Host:    <------- ??23 <--------- 23 <------- DS1307      (Read Operation)

We have no idea if the year is 2023,2123,2223 etc. How do I then construct the unix timestamp?

bessman commented 1 year ago

Hey, How do we identify if the host wants 12hr or 24 hour time format. Based on the 32bit unix stamp we can't decide right? Do we have another data byte to read from which specifies what kind of time_format to be used?

Let's just go with 24h time, all the time.

Another thing I noticed is the DS1307 supports year in format [00-99]. While reading the year from DS1307 and converting it back to unix timestamp I have no way of knowing which year it belongs to.

Host:    -------> 2023  ---------> 23 -------> DS1307      (Write Operation)
Host:    <------- ??23 <--------- 23 <------- DS1307      (Read Operation)

We have no idea if the year is 2023,2123,2223 etc. How do I then construct the unix timestamp?

Hmm, tricky. We could store the first two year digits in flash, but that would increase the complexity of this feature by a lot. Too much, in my opinion, for what is essentially an edge case.

Let's keep it simple:

  1. When getting the time, assume the year is 20XX.
  2. When setting the time, if the first two digits are not 20, return ARGUMENT_ERROR and do nothing.

Another question is whether to treat the unix timestamp as signed (representable range 1900-2038) or unsigned (representable range 1970-2106). Let's go with the latter; it conveniently overlaps to a large extent with FatFS's fattime.