Example #1
0
    def do_send_recvs(self):
        meter_packet = np.zeros(METERING_PACKET_SIZE, dtype=np.float64)
        first_meter_index_needed = 0
        while True:
            dirty = self._param_mem_dirty.nonzero()[0]
            meter_words_desired = METERING_PACKET_SIZE - first_meter_index_needed
            if len(dirty) == 0:
                if meter_words_desired <= 0:
                    # All sending and receiving this time is complete.
                    break
                # Otherwise, pick a random address to start from
                first_param_send_index = random.randrange(max(0, len(self._param_mem_contents) - self.spi_words))
            else:
                first_param_send_index = dirty[0]
            param_data_to_send = self._param_mem_contents[first_param_send_index:]
            if len(param_data_to_send) > self.spi_words:
                param_data_to_send = param_data_to_send[: self.spi_words]
            words_in_transfer = len(param_data_to_send)

            read_buf = self._read_buf[:words_in_transfer]

            # Unpack floats into fixed point in the write buffer.
            write_buf = self._write_buf[:words_in_transfer]
            wireformat.floats_to_fixeds(param_data_to_send, PARAM_INT_BITS, PARAM_FRAC_BITS, write_buf.view(np.int64))

            # print '{} @ rd: {} wr: {}'.format(words_in_transfer, first_meter_index_needed, first_param_send_index)
            self.spi_channel.transfer(
                read_addr=first_meter_index_needed,
                read_data=read_buf,
                write_addr=first_param_send_index,
                write_data=write_buf,
            )

            # Mark param memory segment not dirty.
            self._param_mem_dirty[first_param_send_index : first_param_send_index + words_in_transfer] = 0

            # Extract the metering data we got.
            meter_vals_read = read_buf[:meter_words_desired]
            wireformat.sign_extend(meter_vals_read, METER_SIGN_BIT)
            wireformat.fixeds_to_floats(
                meter_vals_read.view(np.int64),
                METER_FRAC_BITS,
                meter_packet[first_meter_index_needed : first_meter_index_needed + len(meter_vals_read)],
            )
            # TODO: wraparound, since the meter data at the beginning of the packet is going to be newer.
            first_meter_index_needed += words_in_transfer
            break  # FIXME.

        self._meter_revision += 1

        np.maximum(2 ** -METER_FRAC_BITS, meter_packet, out=meter_packet)
        # meter packet contains LPF of square of signal value right-shifted by 2 bits.
        # So: correct for the shift, correct for the crest factor, sqrt, and convert to dB.
        meter_values = 20 * np.log10(np.sqrt(meter_packet * 2 ** 2 * 2))
        self._meter_mem_contents = (self._meter_revision, meter_values)
Example #2
0
def test_fixed_to_float():
    ref    = np.array([2**-30, -(2**-30),     1,     -1, 2**5 - 2**-30, -2**5 ])
    fixeds = np.array([     1,        -1, 2**30, -2**30,     2**35 - 1, -2**35], dtype=np.int64)
    out = np.empty(len(fixeds), dtype=np.float64)
    wireformat.fixeds_to_floats(fixeds, 30, out)
    assert np.all(out == ref)