import math
def constrain(val, _max, _min):
return int(min(max(val, _min), _max))
def generate_mif(file_name, width, depth, rom):
f = open(file_name, "w")
f.write("WIDTH=%d;\n" % width)
f.write("DEPTH=%d;\n" % depth)
f.write("ADDRESS_RADIX=UNS;\n")
f.write("DATA_RADIX=BIN;\n")
f.write("CONTENT BEGIN\n")
format_of_code = "0" + str(width) + "b"
for i in range(depth):
machine_code = format(rom[i], format_of_code)
f.write("%10d : %s;\n" % (i, machine_code))
f.write("END;\n")
f.close()
def mov(ra, rb): return 0 << 11 | ra << 8 | rb << 5
def add(ra, rb): return 1 << 11 | ra << 8 | rb << 5
def sub(ra, rb): return 2 << 11 | ra << 8 | rb << 5
def _and(ra, rb): return 3 << 11 | ra << 8 | rb << 5
def _or(ra, rb): return 4 << 11 | ra << 8 | rb << 5
def sl(ra): return 5 << 11 | ra << 8
def sr(ra): return 6 << 11 | ra << 8
def jmp_reg(ra): return 7 << 11 | ra << 8
def ldl(ra, ival): return 8 << 11 | ra << 8 | (ival & 0xFF)
def ldh(ra, ival): return 9 << 11 | ra << 8 | (ival & 0xFF)
def cmp(ra, rb): return 10 << 11 | ra << 8 | rb << 5
def je(addr): return 11 << 11 | (addr & 0xFF)
def jmp(addr): return 12 << 11 | (addr & 0xFF)
def ld(ra, addr): return 13 << 11 | ra << 8 | (addr & 0xFF)
def st(ra, addr): return 14 << 11 | ra << 8 | (addr & 0xFF)
def jnc(addr): return 15 << 11 | (addr & 0xFF)
def nop() : return 0
def _in(ra): return ld(ra, 65)
def out(ra): return st(ra, 64)
def ld_hl(ra, two_bytes):
return ldh(ra, two_bytes >> 8), \
ldl(ra, two_bytes & 0xFF)
FILE_NAME = "rom_init.mif"
WIDTH = 15
DEPTH = 256
_ = [0] * DEPTH
F_CPU = 10E3
DELAY_40ms = 40E-3
DELAY_20ms = 20E-3
DELAY_2ms = 2E-3
DELAY_100us = 100E-6
DELAY_50us = 50E-6
LOOPS_for_40ms = constrain(math.ceil((DELAY_40ms * F_CPU - 16) / 8 - 1), 2**16-1, 0)
LOOPS_for_2ms = constrain(math.ceil((DELAY_2ms * F_CPU - 16) / 8 - 1), 2**16-1, 0)
LOOPS_for_100us = constrain(math.ceil((DELAY_100us * F_CPU - 16) / 8 - 1), 2**16-1, 0)
FUNC_SET = 0b111000
DISP_CNT = 0b1100
CLS = 0b1
ENT_MOD = 0b110
LEFT_MOST = [0x80, 0xC0]
r0, r1, r2, r3, r4, r5, r6, r7 = range(8)
COUNTER = r0
OUT = r1
RET_TO = r2
TMP0 = r3
TMP1 = r4
VAL = r5
def call(go_to, return_to):
return ldl(RET_TO, return_to), \
jmp(go_to)
def ret():
return jmp_reg(RET_TO)
def set_RC(r, c):
return ldl(OUT, LEFT_MOST[r] + c)
def reverse_4nibles(two_bytes):
return eval("0x" + ((str(hex(two_bytes))[2:])[::-1]))
DELAY_40MS = 245
_[(pc := DELAY_40MS)] = ldl(TMP0, 1)
_[(pc := pc+1)], \
_[(pc := pc+1)] = ld_hl(COUNTER, LOOPS_for_40ms)
_[(pc := pc+1)] = sub(COUNTER, TMP0)
_[(pc := pc+1)] = jnc(pc)
_[(pc := pc+1)] = ret()
COMMAND_W = 230
_[(pc := COMMAND_W)] = out(OUT)
_[(pc := pc+1)] = ldh(OUT, 0b00)
_[(pc := pc+1)] = out(OUT)
_[(pc := pc+1)] = ldh(OUT, 0b10)
_[(pc := pc+1)] = out(OUT)
_[(pc := pc+1)] = nop()
_[(pc := pc+1)] = ldh(OUT, 0b00)
_[(pc := pc+1)] = out(OUT)
_[(pc := pc+1)] = ldl(TMP0, 1)
_[(pc := pc+1)], \
_[(pc := pc+1)] = ld_hl(COUNTER, LOOPS_for_100us)
_[(pc := pc+1)] = sub(COUNTER, TMP0)
_[(pc := pc+1)] = jnc(pc)
_[(pc := pc+1)] = ret()
DELAY_2MS = 220
_[(pc := DELAY_2MS)] = ldl(TMP0, 1)
_[(pc := pc+1)], \
_[(pc := pc+1)] = ld_hl(COUNTER, LOOPS_for_2ms)
_[(pc := pc+1)] = sub(COUNTER, TMP0)
_[(pc := pc+1)] = jnc(pc)
_[(pc := pc+1)] = ret()
DATA_W = 205
_[(pc := DATA_W)] = out(OUT)
_[(pc := pc+1)] = ldh(OUT, 0b11)
_[(pc := pc+1)] = out(OUT)
_[(pc := pc+1)] = nop()
_[(pc := pc+1)] = ldh(OUT, 0b01)
_[(pc := pc+1)] = out(OUT)
_[(pc := pc+1)] = ldl(TMP0, 1)
_[(pc := pc+1)], \
_[(pc := pc+1)] = ld_hl(COUNTER, LOOPS_for_100us)
_[(pc := pc+1)] = sub(COUNTER, TMP0)
_[(pc := pc+1)] = jnc(pc)
_[(pc := pc+1)] = ret()
VAL_TO_HEX = 190
_[(pc := VAL_TO_HEX)] = mov(OUT, VAL)
_[(pc := pc+1)] = ldl(TMP0, 0xF)
_[(pc := pc+1)] = _and(OUT, TMP0)
_[(pc := pc+1)] = ldl(TMP0, 10)
_[(pc := pc+1)] = mov(TMP1, OUT)
_[(pc := pc+1)] = sub(TMP1, TMP0)
_[(pc := pc+1)] = jnc(pc+5)
_[(pc := pc+1)] = ldl(TMP0, ord('0') )
_[(pc := pc+1)] = add(OUT, TMP0)
_[(pc := pc+1)] = jmp(pc+4)
_[(pc := pc+1)] = ldl(TMP0, ord('A') - 0xA)
_[(pc := pc+1)] = add(OUT, TMP0)
_[(pc := pc+1)] = ret()
VAL_SR_4 = 185
_[(pc := VAL_SR_4)] = sr(VAL)
_[(pc := pc+1)] = sr(VAL)
_[(pc := pc+1)] = sr(VAL)
_[(pc := pc+1)] = sr(VAL)
_[(pc := pc+1)] = ret()
DELAY_100US = 175
_[(pc := DELAY_100US)] = ldl(TMP0, 1)
_[(pc := pc+1)], \
_[(pc := pc+1)] = ld_hl(COUNTER, LOOPS_for_100us)
_[(pc := pc+1)] = sub(COUNTER, TMP0)
_[(pc := pc+1)] = jnc(pc)
_[(pc := pc+1)] = ret()
ad = -1
_[(ad := ad+1)] = ldh(OUT, 0b00)
_[(ad := ad+1)] = out(OUT)
_[(ad := ad+1)], \
_[(ad := ad+1)] = call(DELAY_40MS, ad+3)
_[(ad := ad+1)] = ldl(OUT, FUNC_SET)
_[(ad := ad+1)], \
_[(ad := ad+1)] = call(COMMAND_W, ad+3)
_[(ad := ad+1)] = ldl(OUT, DISP_CNT)
_[(ad := ad+1)], \
_[(ad := ad+1)] = call(COMMAND_W, ad+3)
_[(ad := ad+1)] = ldl(OUT, CLS)
_[(ad := ad+1)], \
_[(ad := ad+1)] = call(COMMAND_W, ad+3)
_[(ad := ad+1)], \
_[(ad := ad+1)] = call(DELAY_2MS, ad+3)
_[(ad := ad+1)] = ldl(OUT, ENT_MOD)
_[(ad := ad+1)], \
_[(ad := ad+1)] = call(COMMAND_W, ad+3)
RETURN_HERE = ad+1
_[(ad := ad+1)] = _in(VAL)
_[(ad := ad+1)] = set_RC(0, 3)
_[(ad := ad+1)], \
_[(ad := ad+1)] = call(COMMAND_W, ad+3)
_[(ad := ad+1)], \
_[(ad := ad+1)] = call(VAL_TO_HEX, ad+3)
_[(ad := ad+1)], \
_[(ad := ad+1)] = call(DATA_W, ad+3)
_[(ad := ad+1)], \
_[(ad := ad+1)] = call(VAL_SR_4, ad+3)
_[(ad := ad+1)] = set_RC(0, 2)
_[(ad := ad+1)], \
_[(ad := ad+1)] = call(COMMAND_W, ad+3)
_[(ad := ad+1)], \
_[(ad := ad+1)] = call(VAL_TO_HEX, ad+3)
_[(ad := ad+1)], \
_[(ad := ad+1)] = call(DATA_W, ad+3)
_[(ad := ad+1)], \
_[(ad := ad+1)] = call(VAL_SR_4, ad+3)
_[(ad := ad+1)] = set_RC(0, 1)
_[(ad := ad+1)], \
_[(ad := ad+1)] = call(COMMAND_W, ad+3)
_[(ad := ad+1)], \
_[(ad := ad+1)] = call(VAL_TO_HEX, ad+3)
_[(ad := ad+1)], \
_[(ad := ad+1)] = call(DATA_W, ad+3)
_[(ad := ad+1)], \
_[(ad := ad+1)] = call(VAL_SR_4, ad+3)
_[(ad := ad+1)] = set_RC(0, 0)
_[(ad := ad+1)], \
_[(ad := ad+1)] = call(COMMAND_W, ad+3)
_[(ad := ad+1)], \
_[(ad := ad+1)] = call(VAL_TO_HEX, ad+3)
_[(ad := ad+1)], \
_[(ad := ad+1)] = call(DATA_W, RETURN_HERE)
_[255] = jmp(255)
generate_mif(FILE_NAME, WIDTH, DEPTH, _)