Exemple #1
0
class DeepSleep:

    WPUA_ADDR = const(0x09)
    OPTION_REG_ADDR = const(0x0E)
    IOCAP_ADDR = const(0x1A)
    IOCAN_ADDR = const(0x1B)

    WAKE_STATUS_ADDR = const(0x40)
    MIN_BAT_ADDR = const(0x41)
    SLEEP_TIME_ADDR = const(0x42)
    CTRL_0_ADDR = const(0x45)

    EXP_RTC_PERIOD = const(7000)

    def __init__(self):
        self.uart = UART(1, baudrate=10000, pins=(COMM_PIN, ), timeout_chars=5)
        self.clk_cal_factor = 1
        self.uart.read()
        # enable the weak pull-ups control
        self.clearbits(OPTION_REG_ADDR, 1 << 7)

    def _send(self, data):
        self.uart.write(bytes(data))

    def _start(self):
        self.uart.sendbreak(12)
        self._send([0x55])

    def _magic(self, address, and_val, or_val, xor_val, expected=None):
        self._start()
        self._send([address, and_val & 0xFF, or_val & 0xFF, xor_val & 0xFF])
        if expected is None:
            return self.uart.read()
        else:
            if expected > 0:
                return self.uart.read(expected)

    def _add_to_pin_mask(self, mask, pin):
        if pin == 'P10' or pin == 'G17':
            mask |= 0x01
        elif pin == 'P17' or pin == 'G31':
            mask |= 0x02
        elif pin == 'P18' or pin == 'G30':
            mask |= 0x08
        else:
            raise ValueError('Invalid Pin specified: {}'.format(pin))
        return mask

    def _create_pin_mask(self, pins):
        mask = 0
        if type(pins) is str:
            mask = self._add_to_pin_mask(mask, pins)
        else:
            for pin in pins:
                mask = self._add_to_pin_mask(mask, pin)
        return mask & PIN_MASK

    def poke(self, address, value):
        self._magic(address, 0, value, 0)

    def peek(self, address):
        try:
            return self._magic(address, 0xFF, 0, 0)[6]
        except:
            return self._magic(address, 0xFF, 0, 0)[6]

    def setbits(self, address, mask):
        self._magic(address, 0xFF, mask, 0)

    def clearbits(self, address, mask):
        self._magic(address, ~mask, 0, 0)

    def togglebits(self, address, mask):
        self._magic(address, 0xFF, 0, mask)

    def calibrate(self):
#         The microcontroller will send the value of CTRL_0 after setting the bit
#            and then will send the following pattern through the data line:
#
#               val | 1 | 0 | 1*| 0 | 1*| 0 | 1
#               ms  | 1 | 1 | 1 | 1 | 8 | 1 | -
#
#            The idea is to measure the real life duration of periods marked with *
#            and substract them. That will remove any errors common to both measurements
#            The result is 7 ms as generated by the PIC LF clock.
#            It can be used to scale any future sleep value.

        # setbits, but limit the number of received bytes to avoid confusion with pattern
        self._magic(CTRL_0_ADDR, 0xFF, 1 << 2, 0, 0)
        self.uart.deinit()
        self._pulses = pycom.pulses_get(COMM_PIN, 150)
        self.uart.init(baudrate=10000, pins=(COMM_PIN, ), timeout_chars=5)
        idx = 0
        for i in range(len(self._pulses)):
            if self._pulses[i][1] > EXP_RTC_PERIOD:
                idx = i
                break
        try:
            self.clk_cal_factor = (self._pulses[idx][1] - self._pulses[(idx - 1)][1]) / EXP_RTC_PERIOD
        except:
            self.clk_cal_factor = 1
        if self.clk_cal_factor > 1.25 or self.clk_cal_factor < 0.75:
            self.clk_cal_factor = 1

    def enable_auto_poweroff(self):
        self.setbits(CTRL_0_ADDR, 1 << 1)

    def enable_pullups(self, pins):
        mask = self._create_pin_mask(pins)
        self.setbits(WPUA_ADDR, mask)

    def disable_pullups(self, pins):
        mask = self._create_pin_mask(pins)
        self.clearbits(WPUA_ADDR, mask)

    def enable_wake_on_raise(self, pins):
        mask = self._create_pin_mask(pins)
        self.setbits(IOCAP_ADDR, mask)

    def disable_wake_on_raise(self, pins):
        mask = self._create_pin_mask(pins)
        self.clearbits(IOCAP_ADDR, mask)

    def enable_wake_on_fall(self, pins):
        mask = self._create_pin_mask(pins)
        self.setbits(IOCAN_ADDR, mask)

    def disable_wake_on_fall(self, pins):
        mask = self._create_pin_mask(pins)
        self.clearbits(IOCAN_ADDR, mask)

    def get_wake_status(self):
        # bits as they are returned from PIC:
        #   0: PIN 0 value after awake
        #   1: PIN 1 value after awake
        #   2: PIN 2 value after awake
        #   3: PIN 3 value after awake
        #   4: TIMEOUT
        #   5: POWER ON

        wake_r = self.peek(WAKE_STATUS_ADDR)
        return {'wake': wake_r & (TIMER_WAKE | POWER_ON_WAKE),
                'P10': wake_r & 0x01, 'P17': (wake_r & 0x02) >> 1,
                'P18': (wake_r & 0x08) >> 3}

    def set_min_voltage_limit(self, value):
        # voltage value passed in volts (e.g. 3.6) and round it to the nearest integer
        value = int(((256 * 2.048) + (value / 2)) / value)
        self.poke(MIN_BAT_ADDR, value)

    def go_to_sleep(self, seconds):
        gc.collect()
        while True:
            try:
                self.calibrate()
            except Exception:
                pass

            # the 1.024 factor is because the PIC LF operates at 31 KHz
            # WDT has a frequency divider to generate 1 ms
            # and then there is a binary prescaler, e.g., 1, 2, 4 ... 512, 1024 ms
            # hence the need for the constant

            # round to the nearest integer
            seconds = int((seconds / (1.024 * self.clk_cal_factor)) + 0.5)
            self.poke(SLEEP_TIME_ADDR, (seconds >> 16) & 0xFF)
            self.poke(SLEEP_TIME_ADDR + 1, (seconds >> 8) & 0xFF)
            self.poke(SLEEP_TIME_ADDR + 2, seconds & 0xFF)
            self.setbits(CTRL_0_ADDR, 1 << 0)

    def hw_reset(self):
        self.setbits(CTRL_0_ADDR, 1 << 4)
Exemple #2
0
        [("GP16", "GP17"), ("GP16", "GP17", "GP7", "GP6")],
    ]
else:
    raise Exception("Board not supported!")

# just in case we have the repl duplicated on any of the uarts
os.dupterm(None)

for uart_id in uart_id_range:
    uart = UART(uart_id, 38400)
    print(uart)
    uart.init(57600, 8, None, 1, pins=uart_pins[uart_id][0])
    uart.init(baudrate=9600, stop=2, parity=UART.EVEN, pins=uart_pins[uart_id][1])
    uart.init(baudrate=115200, parity=UART.ODD, stop=0, pins=uart_pins[uart_id][0])
    uart = UART(baudrate=1000000)
    uart.sendbreak()

uart = UART(baudrate=1000000)
uart = UART()
print(uart)
uart = UART(baudrate=38400, pins=("GP12", "GP13"))
print(uart)
uart = UART(pins=("GP12", "GP13"))
print(uart)
uart = UART(pins=(None, "GP17"))
print(uart)
uart = UART(baudrate=57600, pins=("GP16", "GP17"))
print(uart)

# now it's time for some loopback tests between the uarts
uart0 = UART(0, 1000000, pins=uart_pins[0][0])
Exemple #3
0
    uart_id_range = range(0, 2)
    uart_pins = [[('GP12', 'GP13'), ('GP12', 'GP13', 'GP7', 'GP6')], [('GP16', 'GP17'), ('GP16', 'GP17', 'GP7', 'GP6')]]
else:
    raise Exception('Board not supported!')

# just in case we have the repl duplicated on any of the uarts
os.dupterm(None)

for uart_id in uart_id_range:
    uart = UART(uart_id, 38400)
    print(uart)
    uart.init(57600, 8, None, 1, pins=uart_pins[uart_id][0])
    uart.init(baudrate=9600, stop=2, parity=UART.EVEN, pins=uart_pins[uart_id][1])
    uart.init(baudrate=115200, parity=UART.ODD, stop=0, pins=uart_pins[uart_id][0])
    uart = UART(baudrate=1000000)
    uart.sendbreak()

uart = UART(baudrate=1000000)
uart = UART()
print(uart)
uart = UART(baudrate=38400, pins=('GP12', 'GP13'))
print(uart)
uart = UART(pins=('GP12', 'GP13'))
print(uart)
uart = UART(pins=(None, 'GP17'))
print(uart)
uart = UART(baudrate=57600, pins=('GP16', 'GP17'))
print(uart)

# now it's time for some loopback tests between the uarts
uart0 = UART(0, 1000000, pins=uart_pins[0][0])
Exemple #4
0
class DeepSleep:

    WPUA_ADDR = const(0x09)
    OPTION_REG_ADDR = const(0x0E)
    IOCAP_ADDR = const(0x1A)
    IOCAN_ADDR = const(0x1B)

    WAKE_STATUS_ADDR = const(0x40)
    MIN_BAT_ADDR = const(0x41)
    SLEEP_TIME_ADDR = const(0x42)
    CTRL_0_ADDR = const(0x45)

    EXP_RTC_PERIOD = const(7000)

    def __init__(self):
        self.uart = UART(1, baudrate=10000, pins=(COMM_PIN, ))
        self.clk_cal_factor = 1
        self.uart.read()
        # enable the weak pull-ups control
        self.clearbits(OPTION_REG_ADDR, 1 << 7)

    def _send(self, data):
        self.uart.write(bytes(data))

    def _start(self):
        self.uart.sendbreak(20)
        self._send([0x55])

    def _magic(self, address, and_val, or_val, xor_val, expected=None):
        self._start()
        self._send([address, and_val & 0xFF, or_val & 0xFF, xor_val & 0xFF])
        if expected is None:
            return self.uart.read()
        else:
            if expected > 0:
                return self.uart.read(expected)

    def _add_to_pin_mask(self, mask, pin):
        if pin == 'P10' or pin == 'G17':
            mask |= 0x01
        elif pin == 'P17' or pin == 'G31':
            mask |= 0x02
        elif pin == 'P18' or pin == 'G30':
            mask |= 0x08
        else:
            raise ValueError('Invalid Pin specified: {}'.format(pin))
        return mask

    def _create_pin_mask(self, pins):
        mask = 0
        if type(pins) is str:
            mask = self._add_to_pin_mask(mask, pins)
        else:
            for pin in pins:
                mask = self._add_to_pin_mask(mask, pin)
        return mask & PIN_MASK

    def poke(self, address, value):
        self._magic(address, 0, value, 0)

    def peek(self, address):
        return self._magic(address, 0xFF, 0, 0)[6]

    def setbits(self, address, mask):
        self._magic(address, 0xFF, mask, 0)

    def clearbits(self, address, mask):
        self._magic(address, ~mask, 0, 0)

    def togglebits(self, address, mask):
        self._magic(address, 0xFF, 0, mask)

    def calibrate(self):
        """ The microcontroller will send the value of CTRL_0 after setting the bit
            and then will send the following pattern through the data line:

               val | 1 | 0 | 1*| 0 | 1*| 0 | 1
               ms  | 1 | 1 | 1 | 1 | 8 | 1 | -

            The idea is to measure the real life duration of periods marked with *
            and substract them. That will remove any errors common to both measurements
            The result is 7 ms as generated by the PIC LF clock.
            It can be used to scale any future sleep value. """

        # setbits, but limit the number of received bytes to avoid confusion with pattern
        self._magic(CTRL_0_ADDR, 0xFF, 1 << 2, 0, 0)
        self.uart.deinit()
        self._pulses = pycom.pulses_get(COMM_PIN, 50)
        self.uart = UART(1, baudrate=10000, pins=(COMM_PIN, ))
        try:
            self.clk_cal_factor = (self._pulses[4][1] - self._pulses[1][1]) / EXP_RTC_PERIOD
        except:
            pass
        if self.clk_cal_factor > 1.25 or self.clk_cal_factor < 0.75:
            self.clk_cal_factor = 1

    def enable_auto_poweroff(self):
        self.setbits(CTRL_0_ADDR, 1 << 1)

    def enable_pullups(self, pins):
        mask = self._create_pin_mask(pins)
        self.setbits(WPUA_ADDR, mask)

    def disable_pullups(self, pins):
        mask = self._create_pin_mask(pins)
        self.clearbits(WPUA_ADDR, mask)

    def enable_wake_on_raise(self, pins):
        mask = self._create_pin_mask(pins)
        self.setbits(IOCAP_ADDR, mask)

    def disable_wake_on_raise(self, pins):
        mask = self._create_pin_mask(pins)
        self.clearbits(IOCAP_ADDR, mask)

    def enable_wake_on_fall(self, pins):
        mask = self._create_pin_mask(pins)
        self.setbits(IOCAN_ADDR, mask)

    def disable_wake_on_fall(self, pins):
        mask = self._create_pin_mask(pins)
        self.clearbits(IOCAN_ADDR, mask)

    def get_wake_status(self):
        # bits as they are returned from PIC:
        #   0: PIN 0 value after awake
        #   1: PIN 1 value after awake
        #   2: PIN 2 value after awake
        #   3: PIN 3 value after awake
        #   4: TIMEOUT
        #   5: POWER ON

        wake_r = self.peek(WAKE_STATUS_ADDR)
        return {'wake': wake_r & (TIMER_WAKE | POWER_ON_WAKE),
                'P10': wake_r & 0x01, 'P17': (wake_r & 0x02) >> 1,
                'P18': (wake_r & 0x08) >> 3}

    def set_min_voltage_limit(self, value):
        # voltage value passed in volts (e.g. 3.6) and round it to the nearest integer
        value = int(((256 * 2.048) + (value / 2)) / value)
        self.poke(MIN_BAT_ADDR, value)

    def go_to_sleep(self, seconds):
        gc.collect()
        while True:
            try:
                self.calibrate()
            except Exception:
                pass

            # the 1.024 factor is because the PIC LF operates at 31 KHz
            # WDT has a frequency divider to generate 1 ms
            # and then there is a binary prescaler, e.g., 1, 2, 4 ... 512, 1024 ms
            # hence the need for the constant

            # round to the nearest integer
            seconds = int((seconds / (1.024 * self.clk_cal_factor)) + 0.5)
            self.poke(SLEEP_TIME_ADDR, (seconds >> 16) & 0xFF)
            self.poke(SLEEP_TIME_ADDR + 1, (seconds >> 8) & 0xFF)
            self.poke(SLEEP_TIME_ADDR + 2, seconds & 0xFF)
            self.setbits(CTRL_0_ADDR, 1 << 0)

    def hw_reset(self):
        self.setbits(CTRL_0_ADDR, 1 << 4)