import hid
import struct

bynd = hid.Device(vid=0x35bd, pid=0x1001)

# get software version
bynd.send_feature_report(bytes([0, ord('*')]))
swver = b''
while(len(swver) == 0):
    swver = bynd.read(64,timeout=10)
swver = swver.rstrip(b'\x00')
print("Software version: {}".format(swver[1:].decode('ascii')))

# get the crash reason
bynd.send_feature_report(bytes([0, ord('R')]))
crash_reason = b''
while(len(crash_reason) == 0):
    crash_reason = bynd.read(64,timeout=10)
reasons = struct.unpack("<BHII", crash_reason[1:12])
print("Crash reason: {}".format(reasons[0]))
print("Interrupt IRQn: {}".format(reasons[1]))
print("Hard fault HFSR: 0x{:08X}".format(reasons[2]))
print("Hard fault CFSR: 0x{:08X}".format(reasons[3]))

# get processor registers
bynd.send_feature_report(bytes([0, ord('S'), 0]))
proc_regs = b''
while(len(proc_regs) == 0):
    proc_regs = bynd.read(64,timeout=10)
regs_part1 = struct.unpack("<"+15*"I", proc_regs[4:64])

bynd.send_feature_report(bytes([0, ord('S'), 1]))
proc_regs = b''
while(len(proc_regs) == 0):
    proc_regs = bynd.read(64,timeout=10)
regs_part2 = struct.unpack("<"+15*"I", proc_regs[4:64])
regs_part2_converted = struct.unpack("<"+5*"I"+10*"f", proc_regs[4:64])

bynd.send_feature_report(bytes([0, ord('S'), 2]))
proc_regs = b''
while(len(proc_regs) == 0):
    proc_regs = bynd.read(64,timeout=10)
regs_part3 = struct.unpack("<"+15*"I", proc_regs[4:64])
regs_part3_converted = struct.unpack("<"+15*"f", proc_regs[4:64])

bynd.send_feature_report(bytes([0, ord('S'), 3]))
proc_regs = b''
while(len(proc_regs) == 0):
    proc_regs = bynd.read(64,timeout=10)
regs_part4 = struct.unpack("<"+8*"I", proc_regs[4:36])
regs_part4_converted = struct.unpack("<"+7*"f"+"I", proc_regs[4:36])

for i in range(15):
    print("R{}:\t\t\t0x{:08X}".format(i, regs_part1[i]))

print("R15:\t\t\t0x{:08X}".format(regs_part2[0]))
print("PSR:\t\t\t0x{:08X}".format(regs_part2[1]))
print("MSP:\t\t\t0x{:08X}".format(regs_part2[2]))
print("PSP:\t\t\t0x{:08X}".format(regs_part2[3]))
print("Exception PSR:\t\t0x{:08X}".format(regs_part2[4]))
for i in range(10):
    print("S{}:\t\t\t0x{:08X}({:.6f})".format(i, regs_part2[5+i],regs_part2_converted[5+i]))
for i in range(15):
    print("S{}:\t\t\t0x{:08X}({:.6f})".format(i+10, regs_part3[i],regs_part3_converted[i]))
for i in range(7):
    print("S{}:\t\t\t0x{:08X}({:.6f})".format(i+25, regs_part4[i],regs_part4_converted[i]))
print("FPSCR:\t\t\t0x{:08X}".format(regs_part4[7]))

# print memory sections
bynd.send_feature_report(bytes([0, ord('G')]))
num_mem_sections = b''
while(len(num_mem_sections) == 0):
    num_mem_sections = bynd.read(64, timeout=10)

num_mem_sections = num_mem_sections[1] # just get the number

# Get memory region info
regions = []
for i in range(num_mem_sections):
    bynd.send_feature_report(bytes([0, ord('I'), i]))
    region_info = b''
    while(len(region_info) == 0):
        region_info = bynd.read(64, timeout=10)
    (startaddr, endaddr) = struct.unpack("<II",region_info[4:12])
    region_name = region_info[12:].rstrip(b'\x00').decode('ascii')
    regions.append((region_name, startaddr, endaddr))

for reg in regions:
    print("Region {}: 0x{:08X} to 0x{:08X}".format(reg[0], reg[1], reg[2]))