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)
def dump_to_mif(self, outfile): self.handle_queued_memory_mods() write_buf = np.empty(len(self._param_mem_contents), dtype=np.uint64) wireformat.floats_to_fixeds(self._param_mem_contents, PARAM_INT_BITS, PARAM_FRAC_BITS, write_buf.view(np.int64)) print >> outfile, "DEPTH = {};".format(len(write_buf)) print >> outfile, "WIDTH = {};".format(36) print >> outfile, "ADDRESS_RADIX = HEX;" print >> outfile, "DATA_RADIX = HEX;" print >> outfile, "CONTENT BEGIN" for addr, val in enumerate(write_buf): fmt_val = "{:09x}".format(val) # But if it was negative, it's too wide. fmt_val = fmt_val[-9:] print >> outfile, "{:02x} : {};".format(addr, fmt_val) print >> outfile, "END;"
def test_float_to_fixed(): # smallest pos, " neg, 1, -1, largest pos, largest neg floats = np.array([2**-30, -(2**-30), 1, -1, 2**5 - 2**-30, -2**5 ]) ref = np.array([ 1, -1, 2**30, -2**30, 2**35 - 1, -2**35], dtype=np.int64) out = np.empty(len(floats), dtype=np.int64) overflow = wireformat.floats_to_fixeds(floats, 5, 30, out) assert np.all(out == ref) assert not overflow # Test overflow floats = np.array([ 2**5, -2**5 - 2**-30]) ref = np.array([2**35 - 1, -2**35], dtype=np.int64) out = np.empty(len(floats), dtype=np.int64) overflow = wireformat.floats_to_fixeds(floats, 5, 30, out) assert np.all(out == ref) assert overflow