Example #1
0
class EmulateEfuseControllerBase(object):
    """ The class for virtual efuse operations. Using for HOST_TEST.
    """

    CHIP_NAME = ""
    mem = None
    debug = False
    Blocks = None
    Fields = None
    REGS = None

    def __init__(self, efuse_file=None, debug=False):
        self.debug = debug
        self.efuse_file = efuse_file
        if self.efuse_file:
            try:
                self.mem = BitString(open(self.efuse_file, 'a+b'),
                                     length=(self.REGS.EFUSE_MEM_SIZE
                                             & self.REGS.EFUSE_ADDR_MASK) * 8)
            except ValueError:
                # the file is empty or does not fit the length.
                self.mem = BitString(length=(self.REGS.EFUSE_MEM_SIZE
                                             & self.REGS.EFUSE_ADDR_MASK) * 8)
                self.mem.set(0)
                self.mem.tofile(open(self.efuse_file, 'a+b'))
        else:
            # efuse_file is not provided it means we do not want to keep the result of efuse operations
            self.mem = BitString(
                (self.REGS.EFUSE_MEM_SIZE & self.REGS.EFUSE_ADDR_MASK) * 8)
            self.mem.set(0)

    """ esptool method start >> """

    def read_efuse(self, n, block=0):
        """ Read the nth word of the ESP3x EFUSE region. """
        blk = self.Blocks.get(self.Blocks.BLOCKS[block])
        return self.read_reg(blk.rd_addr + (4 * n))

    def read_reg(self, addr):
        self.mem.pos = self.mem.length - (
            (addr & self.REGS.EFUSE_ADDR_MASK) * 8 + 32)
        return self.mem.read("uint:32")

    def write_reg(self,
                  addr,
                  value,
                  mask=0xFFFFFFFF,
                  delay_us=0,
                  delay_after_us=0):
        self.mem.pos = self.mem.length - (
            (addr & self.REGS.EFUSE_ADDR_MASK) * 8 + 32)
        self.mem.overwrite("uint:32={}".format(value & mask))
        self.handle_writing_event(addr, value)

    def update_reg(self, addr, mask, new_val):
        position = self.mem.length - (
            (addr & self.REGS.EFUSE_ADDR_MASK) * 8 + 32)
        self.mem.pos = position
        cur_val = self.mem.read("uint:32")
        self.mem.pos = position
        self.mem.overwrite("uint:32={}".format(cur_val | (new_val & mask)))

    def write_efuse(self, n, value, block=0):
        """ Write the nth word of the ESP3x EFUSE region. """
        blk = self.Blocks.get(self.Blocks.BLOCKS[block])
        self.write_reg(blk.wr_addr + (4 * n), value)

    """ << esptool method end """

    def handle_writing_event(self, addr, value):
        self.save_to_file()

    def save_to_file(self):
        if self.efuse_file:
            with open(self.efuse_file, 'wb') as f:
                self.mem.tofile(f)

    def handle_coding_scheme(self, blk, data):
        return data

    def copy_blocks_wr_regs_to_rd_regs(self, updated_block=None):
        for b in reversed(self.Blocks.BLOCKS):
            blk = self.Blocks.get(b)
            if updated_block is not None:
                if blk.id != updated_block:
                    continue
            data = self.read_block(blk.id, wr_regs=True)
            if self.debug:
                print(blk.name, data.hex)
            plain_data = self.handle_coding_scheme(blk, data)
            plain_data = self.check_wr_protection_area(blk.id, plain_data)
            self.update_block(blk, plain_data)

    def clean_blocks_wr_regs(self):
        for b in self.Blocks.BLOCKS:
            blk = self.Blocks.get(b)
            for offset in range(0, blk.len * 4, 4):
                wr_addr = blk.wr_addr + offset
                self.write_reg(wr_addr, 0)

    def read_field(self, name, bitstring=True):
        for e in self.Fields.EFUSES:
            field = self.Fields.get(e)
            if field.name == name:
                self.read_block(field.block)
                block = self.read_block(field.block)
                if field.type.startswith("bool"):
                    field_len = 1
                else:
                    field_len = int(re.search(r'\d+', field.type).group())
                    if field.type.startswith("bytes"):
                        field_len *= 8
                block.pos = block.length - (field.word * 32 + field.pos +
                                            field_len)
                if bitstring:
                    return block.read(field_len)
                else:
                    return block.read(field.type)
        return None

    def get_bitlen_of_block(self, blk, wr=False):
        return 32 * blk.len

    def read_block(self, idx, wr_regs=False):
        block = None
        for b in self.Blocks.BLOCKS:
            blk = self.Blocks.get(b)
            if blk.id == idx:
                blk_len_bits = self.get_bitlen_of_block(blk, wr=wr_regs)
                addr = blk.wr_addr if wr_regs else blk.rd_addr
                self.mem.pos = self.mem.length - (
                    (addr & self.REGS.EFUSE_ADDR_MASK) * 8 + blk_len_bits)
                block = self.mem.read(blk_len_bits)
                break
        return block

    def update_block(self, blk, wr_data):
        wr_data = self.read_block(blk.id) | wr_data
        self.overwrite_mem_from_block(blk, wr_data)

    def overwrite_mem_from_block(self, blk, wr_data):
        self.mem.pos = self.mem.length - (
            (blk.rd_addr & self.REGS.EFUSE_ADDR_MASK) * 8 + wr_data.len)
        self.mem.overwrite(wr_data)

    def check_wr_protection_area(self, num_blk, wr_data):
        # checks fields which have the write protection bit.
        # if the write protection bit is set then we need to protect that area from changes.
        write_disable_bit = self.read_field("WR_DIS", bitstring=False)
        mask_wr_data = BitString(len(wr_data))
        mask_wr_data.set(0)
        blk = self.Blocks.get(self.Blocks.BLOCKS[num_blk])
        if blk.write_disable_bit is not None and write_disable_bit & (
                1 << blk.write_disable_bit):
            mask_wr_data.set(1)
        else:
            for e in self.Fields.EFUSES:
                field = self.Fields.get(e)
                if blk.id == field.block and field.block == num_blk:
                    if field.write_disable_bit is not None and write_disable_bit & (
                            1 << field.write_disable_bit):
                        data = self.read_field(field.name)
                        data.set(1)
                        mask_wr_data.pos = mask_wr_data.length - (
                            field.word * 32 + field.pos + data.len)
                        mask_wr_data.overwrite(data)
        mask_wr_data.invert()
        return wr_data & mask_wr_data

    def check_rd_protection_area(self):
        # checks fields which have the read protection bits.
        # if the read protection bit is set then we need to reset this field to 0.
        read_disable_bit = self.read_field("RD_DIS", bitstring=False)
        for b in self.Blocks.BLOCKS:
            blk = self.Blocks.get(b)
            block = self.read_block(blk.id)
            if blk.read_disable_bit is not None and read_disable_bit & (
                    1 << blk.read_disable_bit):
                block.set(0)
            else:
                for e in self.Fields.EFUSES:
                    field = self.Fields.get(e)
                    if blk.id == field.block and field.read_disable_bit is not None and read_disable_bit & (
                            1 << field.read_disable_bit):
                        raw_data = self.read_field(field.name)
                        raw_data.set(0)
                        block.pos = block.length - (
                            field.word * 32 + field.pos + raw_data.length)
                        block.overwrite(BitString(raw_data.length))
            self.overwrite_mem_from_block(blk, block)

    def clean_mem(self):
        self.mem.set(0)
        if self.efuse_file:
            with open(self.efuse_file, 'wb') as f:
                self.mem.tofile(f)
Example #2
0
def generate(height, codepoints, font_file_path, output_file_name, packed, code, smoke):
    font = Font(font_file_path, height)

    if smoke:
        glyphs = [chr(x) for x in codepoints]
        f = sys.stdout.buffer
        if output_file_name is not None:
            f = open(output_file_name, 'wt')

        for cur_glyph in glyphs:
            ch = font.render_character(cur_glyph)
            f.write(cur_glyph + '\n')
            f.write(repr(ch))
            f.write('\n\n')

        f.close()
        return

    ili9341_t3_font = OrderedDict()
    ili9341_t3_font['index'] = 0
    ili9341_t3_font['unicode'] = 0
    ili9341_t3_font['data'] = 0
    ili9341_t3_font['version'] = 1
    ili9341_t3_font['reserved'] = 0
    ili9341_t3_font['index1_first'] = (len(codepoints) & 0xff00) >> 8
    ili9341_t3_font['index1_last'] = len(codepoints) & 0xff
    ili9341_t3_font['index2_first'] = 0
    ili9341_t3_font['index2_last'] = 0
    ili9341_t3_font['bits_index'] = 0
    ili9341_t3_font['bits_width'] = 0
    ili9341_t3_font['bits_height'] = 0
    ili9341_t3_font['bits_xoffset'] = 0
    ili9341_t3_font['bits_yoffset'] = 0
    ili9341_t3_font['bits_delta'] = 0
    ili9341_t3_font['line_space'] = font.height
    e_cap = font.glyph_for_character('E')
    ili9341_t3_font['cap_height'] = e_cap.height - e_cap.descent

    max_width = 1
    max_height = 1
    max_xoffset = 1
    max_yoffset = 1
    max_delta = 1

    glyph_data = dict()

    for codepoint in codepoints:
        cur_glyph = chr(codepoint)
        glyph_header = build_glyph(cur_glyph, font, glyph_data)
        max_width = max(max_width, glyph_header['width'])
        max_height = max(max_height, glyph_header['height'])
        max_xoffset = max(abs(max_xoffset), abs(glyph_header['xoffset']))
        max_yoffset = max(abs(max_yoffset), abs(glyph_header['yoffset']))
        max_delta = max(max_delta, glyph_header['delta'])

    ili9341_t3_font['bits_width'] = int(math.floor(math.log(max_width, 2))) + 1
    ili9341_t3_font['bits_height'] = int(math.floor(math.log(max_height, 2))) + 1
    ili9341_t3_font['bits_xoffset'] = int(math.floor(math.log(max_xoffset, 2))) + 2
    ili9341_t3_font['bits_yoffset'] = int(math.floor(math.log(max_yoffset, 2))) + 2
    ili9341_t3_font['bits_delta'] = int(math.floor(math.log(max_delta, 2))) + 1

    output_data = bytearray()
    index = list()
    total_size = 0

    for codepoint in codepoints:
        ch = chr(codepoint)

        index.append(total_size)
        glyph = glyph_data[ch]
        glyph_bytes = pack_glyph(glyph, ili9341_t3_font)
        output_data.extend(glyph_bytes)
        total_size += len(glyph_bytes)

    ili9341_t3_font['bits_index'] = int(math.floor(math.log(total_size, 2))) + 1

    index_bits = BitString()

    for idx in index:
        index_bits.append(Bits(uint=idx, length=ili9341_t3_font['bits_index']))

    codepoint_table = BitString()
    for codepoint in codepoints:
        codepoint_table.append(Bits(uint=codepoint, length=21))

    if packed:
        f = sys.stdout.buffer

        if output_file_name is not None:
            f = open(output_file_name, 'wb')

        f.write(struct.pack('<3I14Bxx', *tuple(ili9341_t3_font.values())))
        index_bits.tofile(f)
        codepoint_table.tofile(f)
        f.write(output_data)
        f.close()

    if code:
        f = sys.stdout.buffer

        if output_file_name is not None:
            f = open(output_file_name, 'wb')

        variable_name = os.path.splitext(os.path.basename(font_file_path))[0] + '_' + str(height)
        c = io.StringIO()

        c.write('// extern const ILI9341_t3_font_t {};\n\n'.format(variable_name))

        c.write('static const unsigned char {}_data[] = {{\n'.format(variable_name))
        data_byte_array = ['0x' + binascii.hexlify(bytes([x])).decode() for x in output_data]
        for i in range(0, len(data_byte_array), 10):
            c.write(','.join(data_byte_array[i:i + 10]) + ',\n')
        c.write('};\n')
        c.write('/* font data size: {} bytes */\n\n'.format(len(data_byte_array)))

        c.write('static const unsigned char {}_index[] = {{\n'.format(variable_name))
        index_byte_array = ['0x' + binascii.hexlify(bytes([x])).decode() for x in index_bits.tobytes()]
        for i in range(0, len(index_byte_array), 10):
            c.write(','.join(index_byte_array[i:i + 10]) + ',\n')
        c.write('};\n')
        c.write('/* font index size: {} bytes */\n\n'.format(len(index_byte_array)))

        c.write('static const unsigned char {}_codepoints[] = {{\n'.format(variable_name))
        codepoint_byte_array = ['0x' + binascii.hexlify(bytes([x])).decode() for x in codepoint_table.tobytes()]
        for i in range(0, len(codepoint_byte_array), 10):
            c.write(','.join(codepoint_byte_array[i:i + 10]) + ',\n')
        c.write('};\n')
        c.write('/* Unicode codepoint table size: {} bytes */\n\n'.format(len(codepoint_byte_array)))

        c.write('const ILI9341_t3_font_t {} = {{\n'.format(variable_name))
        c.write('    {}_index,\n'.format(variable_name))
        c.write('    {}_codepoints,\n'.format(variable_name))
        c.write('    {}_data,\n'.format(variable_name))
        c.write('    {},\n'.format(ili9341_t3_font['version']))
        c.write('    {},\n'.format(ili9341_t3_font['reserved']))
        c.write('    {},\n'.format(ili9341_t3_font['index1_first']))
        c.write('    {},\n'.format(ili9341_t3_font['index1_last']))
        c.write('    {},\n'.format(ili9341_t3_font['index2_first']))
        c.write('    {},\n'.format(ili9341_t3_font['index2_last']))
        c.write('    {},\n'.format(ili9341_t3_font['bits_index']))
        c.write('    {},\n'.format(ili9341_t3_font['bits_width']))
        c.write('    {},\n'.format(ili9341_t3_font['bits_height']))
        c.write('    {},\n'.format(ili9341_t3_font['bits_xoffset']))
        c.write('    {},\n'.format(ili9341_t3_font['bits_yoffset']))
        c.write('    {},\n'.format(ili9341_t3_font['bits_delta']))
        c.write('    {},\n'.format(ili9341_t3_font['line_space']))
        c.write('    {}\n'.format(ili9341_t3_font['cap_height']))
        c.write('};\n')

        f.write(c.getvalue().encode('ascii'))