summaryrefslogtreecommitdiff
path: root/wasp/drivers/nrf_rtc.py
blob: 100bacd38eed6230482050637a9d9b4231aaeef0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# SPDX-License-Identifier: LGPL-3.0-or-later
# Copyright (C) 2020 Daniel Thompson

"""nRF-family RTC driver
~~~~~~~~~~~~~~~~~~~~~~~~
"""

import machine
import time

#class Stim(object):
#    def __init__(self):
#        self(0)
#
#    def __call__(self, v):
#        self.c = v
#    
#    def counter(self):
#        return self.c

class RTC(object):
    """Real Time Clock based on the nRF-family low power counter.

    .. automethod:: __init__
    """

    def __init__(self, counter):
        """Wrap an RTCounter to provide a fully fledged Real Time Clock.

        If the PNVRAM is valid then we use it to initialize the RTC otherwise
        we just make something up.

        :param RTCounter counter: The RTCCounter channel to adopt.
        """
        self.counter = counter

        if machine.mem32[0x200039c0] == 0x1abe11ed and \
           machine.mem32[0x200039dc] == 0x10adab1e:
            self.lastcount = self.counter.counter()
            self.offset = machine.mem32[0x200039c4]
            self._uptime = machine.mem32[0x200039c8] // 125
        else:
            machine.mem32[0x200039c0] = 0x1abe11ed
            machine.mem32[0x200039dc] = 0x10adab1e
            self._uptime = 0
            self.set_localtime((2020, 3, 1, 3, 0, 0, 0, 0))

    def update(self):
        """Check for counter updates.

        :returns: True of the wall time has changed, False otherwise.
        """
        newcount = self.counter.counter()
        split = newcount - self.lastcount
        if split == 0:
            return False
        if split < 0:
            split += (1 << 24)

        self.lastcount += split
        self.lastcount &= (1 << 24) - 1   
        self._uptime += split
        machine.mem32[0x200039c8] = self._uptime * 125

        return True

    def set_localtime(self, t):
        """Set the current wall time.

        :param sequence t:
                Wall time formatted as (yyyy, mm, dd, HH, MM, SS), any
                additional elements in sequence will be ignored.
        """
        self.lastcount = self.counter.counter()

        if len(t) < 8:
            yyyy = t[0]
            mm = t[1]
            dd = t[2]
            HH = t[3]
            MM = t[4]
            SS = t[5]

            t = (yyyy, mm, dd, HH, MM, SS, 0, 0)

        lt = time.mktime(t)
        self.offset = lt - (self._uptime >> 3)
        machine.mem32[0x200039c4] = self.offset

    def get_localtime(self):
        """Get the current time and date.

        :returns: Wall time formatted as (yyyy, mm, dd, HH, MM, SS, wday, yday)
        """
        self.update()
        return time.localtime(self.offset + (self._uptime >> 3))

    def get_time(self):
        """Get the current time.

        :returns: Wall time formatted as (HH, MM, SS)
        """
        localtime = self.get_localtime()
        return localtime[3:6]

    def time(self):
        """Get time in the same format as time.time"""
        return self.offset + (self._uptime >> 3)

    @property
    def uptime(self):
        """Provide the current uptime in seconds."""
        return self._uptime // 8

    def get_uptime_ms(self):
        """Return the current uptime in milliseconds."""
        return self._uptime * 125