#!/bin/bash

#---------------------------------------#
#   APEX SPI MEMORY PROGRAMMER SCRIPT   #
#---------------------------------------#
# Jonathan Gillard @ Giva Audiovisual Technologies BV 2022

import sys
import json
import os

dsp_variant_filename = '/home/orangepi/IpcSystemService/dsp_variant.txt'
oem_filename = '/home/orangepi/IpcSystemService/oem.json'
spi_read_filename = '/home/orangepi/IpcSystemService/spi_read.txt'
spi_read_length = 79

address = 2048000
block_size = 4096

#Content of dsp_variant.txt
dsp_variant = ""
dsp_hardware = ""
dsp_serial = ""

#Content of oem.json
oem_code = ""

#Content of spi memory
spi_hardware_rev = ""
spi_amp_model = ""
spi_oem_code = ""
spi_serial_number = ""

# read dsp_variant.txt and load content in global parameters
def readDSPVariant():
    global dsp_variant
    global dsp_hardware
    global dsp_serial
    try:
        dsp_file = open(dsp_variant_filename,'r')
        dsp_lines = dsp_file.readlines()
        dsp_param = dsp_lines[0].split()
        dsp_variant = dsp_param[0]
        dsp_hardware = dsp_param[1]
        dsp_serial = dsp_param[2]
        #dsp_param[0] = variantx.code => amplifier model
        #dsp_param[1] = VX.X => dsp software version
        #dsp_param[2] = CPxxxxxxxxx => serial number of amplifier
    except Exception as e:
        return 1
    return 0

# read dsp_oem.json and load content in global parameters
def readOEM():
    global oem_code
    try:
        with open(oem_filename,'r') as oem_file:
            oem_content = json.load(oem_file)
        oem_code = oem_content["oem_code"]
        #check oem length, if empty or len != 10 set 0000000000
        if len(oem_code) != 10:
            oem_code = "0000000000"
    except Exception as e:
        return 1
    return 0

# read spi memory and load content in global parameters
def readSPIMemory():
    global spi_hardware_rev
    global spi_amp_model
    global spi_oem_code
    global spi_serial_number
    #erase previous temp file
    command = "rm " + spi_read_filename
    print(command)
    os.system(command)
    command = "mtd_debug read /dev/mtd0 " + str(address) + " " + str(spi_read_length) + " " + spi_read_filename
    print(command)
    os.system(command)
    #open read file and load global parameters
    try:
        spi_file = open(spi_read_filename)
        spi_lines = spi_file.readlines()
        spi_hardware_rev = spi_lines[0].split(":")[1].rstrip('\n')
        spi_amp_model = spi_lines[1].split(":")[1].rstrip('\n')
        spi_oem_code = spi_lines[2].split(":")[1].rstrip('\n')
        spi_serial_number = spi_lines[3].split(":")[1].rstrip('\n')
    except Exception as e:
        return 1
    return 0

# compare spi memory content with mix of dsp_variant.txt and oem.json
def compare():
    readDSPVariant()
    readOEM()
    if(readSPIMemory() == 0):
        if (dsp_variant == "variant1.code"):
            if (spi_amp_model != "CP0354"):
                print("dsp_variant.txt = " + dsp_variant + " >< spi_model = " + spi_amp_model)
                return 1
        elif (dsp_variant == "variant2.code"):
            if (spi_amp_model != "CP0704"):
                print("dsp_variant.txt = " + dsp_variant + " >< spi_model = " + spi_amp_model)
                return 1
        elif (dsp_variant == "variant3.code"):
            if (spi_amp_model != "CP1504"):
                print("dsp_variant.txt = " + dsp_variant + " >< spi_model = " + spi_amp_model)
                return 1
        elif (dsp_variant == "variant4.code"):
            if (spi_amp_model != "CP3004"):
                print("dsp_variant.txt = " + dsp_variant + " >< spi_model = " + spi_amp_model)
                return 1
        elif (dsp_variant == "variant5.code"):
            if (spi_amp_model != "CP0701"):
                print("dsp_variant.txt = " + dsp_variant + " >< spi_model = " + spi_amp_model)
                return 1
        elif (dsp_variant == "variant6.code"):
            if (spi_amp_model != "CP0702"):
                print("dsp_variant.txt = " + dsp_variant + " >< spi_model = " + spi_amp_model)
                return 1
        elif (dsp_variant == "variant7.code"):
            if (spi_amp_model != "CP0716"):
                print("dsp_variant.txt = " + dsp_variant + " >< spi_model = " + spi_amp_model)
                return 1
        elif (dsp_variant == "variant8.code"):
            if (spi_amp_model != "CP7164"):
                print("dsp_variant.txt = " + dsp_variant + " >< spi_model = " + spi_amp_model)
                return 1
        elif (dsp_variant == "variant9.code"):
            if (spi_amp_model != "CP0703"):
                print("dsp_variant.txt = " + dsp_variant + " >< spi_model = " + spi_amp_model)
                return 1
        else:
            return 1

        if (oem_code != spi_oem_code):
            print("oem.json = " + oem_code + " >< spi_oem_code = " + spi_oem_code)
            return 2

        if (dsp_serial != spi_serial_number):
            print("dsp_variant.txt = " + dsp_serial + " >< spi_oem_code = " + spi_serial_number)
            return 3

        if (dsp_hardware != spi_hardware_rev):
            print("dsp_variant.txt = " + dsp_hardware + " >< spi_hardware_rev = " + spi_hardware_rev)
            return 4
    else:
        return 5
    return 0

# write file in spi memory
def writeSPI():
    global spi_hardware_rev
    global spi_amp_model
    global spi_oem_code
    global spi_serial_number
    #read dsp_variant.txt
    readDSPVariant()
    #read oem_json
    readOEM()
    #Erase memory first
    eraseSPI()
    #Erase temp file to write
    command = "rm " + spi_read_filename
    print(command)
    os.system(command)
    #Write temp file to write
    with open (spi_read_filename, 'w') as f:
        line1 = "Hardware_rev:" + dsp_hardware +"\n"
        line2 = "Amp_model:CP0000\n"
        if (dsp_variant == "variant1.code"):
            line2 = "Amp_model:CP0354\n"
        elif (dsp_variant == "variant2.code"):
            line2 = "Amp_model:CP0704\n"
        elif (dsp_variant == "variant3.code"):
            line2 = "Amp_model:CP1504\n"
        elif (dsp_variant == "variant4.code"):
            line2 = "Amp_model:CP3004\n"
        elif (dsp_variant == "variant5.code"):
            line2 = "Amp_model:CP0701\n"
        elif (dsp_variant == "variant6.code"):
            line2 = "Amp_model:CP0702\n"
        elif (dsp_variant == "variant7.code"):
            line2 = "Amp_model:CP0716\n"
        elif (dsp_variant == "variant8.code"):
            line2 = "Amp_model:CP7164\n"
        elif (dsp_variant == "variant9.code"):
            line2 = "Amp_model:CP0703\n"
        line3 = "OEM_code:" + oem_code + "\n"
        line4 = "Serial_number:" + dsp_serial
        f.writelines([line1, line2, line3, line4])
        f.close()

    #read temp file
    spi_file = open(spi_read_filename)
    spi_lines = spi_file.readlines()
    spi_hardware_rev = spi_lines[0].split(":")[1].rstrip('\n')
    spi_amp_model = spi_lines[1].split(":")[1].rstrip('\n')
    spi_oem_code = spi_lines[2].split(":")[1].rstrip('\n')
    spi_serial_number = spi_lines[3].split(":")[1].rstrip('\n')

    #write temp file to spi memory
    command = "mtd_debug write /dev/mtd0 " + str(address) + " " + str(spi_read_length) + " " + spi_read_filename
    print(command)
    os.system(command)
    #check if temp file is ok
    if (compare() != 0):
        return 1
    return 0

def restore():
    #to implement
    return 0

# erase spi memory blocks (4096)
def eraseSPI():
    command = "mtd_debug erase /dev/mtd0 " + str(address) + " " + str(block_size)
    print(command)
    os.system(command)
    return 0

def bootCheck():
    global spi_hardware_rev
    global spi_amp_model
    global spi_oem_code
    global spi_serial_number
    global dsp_variant
    global dsp_hardware
    global dsp_serial
    global oem_code

    readDSPVariant()
    readOEM()
    #READ SPI MEMORY AND CHECK IF THERE IS CONTENT IN IT
    if(readSPIMemory() == 0):
        dsp_variant_need_update = 0
        oem_need_update = 0
        if(readDSPVariant() == 0):
            if (spi_amp_model == "CP0354"):
                if (dsp_variant != "variant1.code"):
                    dsp_variant_need_update += 1
            elif (spi_amp_model == "CP0704"):
                if (dsp_variant != "variant2.code"):
                    dsp_variant_need_update += 1
            elif (spi_amp_model == "CP1504"):
                if(dsp_variant != "variant3.code"):
                    dsp_variant_need_update += 1
            elif (spi_amp_model == "CP3004"):
                if (dsp_variant != "variant4.code"):
                    dsp_variant_need_update += 1
            elif (spi_amp_model == "CP0701"):
                if (dsp_variant != "variant5.code"):
                    dsp_variant_need_update += 1
            elif (spi_amp_model == "CP0702"):
                if (dsp_variant != "variant6.code"):
                    dsp_variant_need_update += 1
            elif (spi_amp_model == "CP0716"):
                if (dsp_variant != "variant7.code"):
                    dsp_variant_need_update += 1
            elif (spi_amp_model == "CP7164"):
                if (dsp_variant != "variant8.code"):
                    dsp_variant_need_update += 1
            elif (spi_amp_model == "CP0703"):
                if (dsp_variant != "variant9.code"):
                    dsp_variant_need_update += 1
            if (spi_serial_number != dsp_serial):
                    dsp_variant_need_update += 1
            if (spi_hardware_rev != dsp_hardware):
                    dsp_variant_need_update += 1
        else:
            dsp_variant_need_update += 1
        
        if (dsp_variant_need_update > 0):
            if (os.path.exists(dsp_variant_filename)):
                os.remove(dsp_variant_filename)
            else:
                print("File Does Not Exists")
            f = open(dsp_variant_filename, "w")
            if (spi_amp_model == "CP0354"):
                f.write("variant1.code " + str(spi_hardware_rev) + " " + str(spi_serial_number))
            elif (spi_amp_model == "CP0704"):
                f.write("variant2.code " + str(spi_hardware_rev) + " " + str(spi_serial_number))
            elif (spi_amp_model == "CP1504"):
                f.write("variant3.code " + str(spi_hardware_rev) + " " + str(spi_serial_number))
            elif (spi_amp_model == "CP3004"):
                f.write("variant4.code " + str(spi_hardware_rev) + " " + str(spi_serial_number))
            elif (spi_amp_model == "CP0701"):
                f.write("variant5.code " + str(spi_hardware_rev) + " " + str(spi_serial_number))
            elif (spi_amp_model == "CP0702"):
                f.write("variant6.code " + str(spi_hardware_rev) + " " + str(spi_serial_number))
            elif (spi_amp_model == "CP0716"):
                f.write("variant7.code " + str(spi_hardware_rev) + " " + str(spi_serial_number))
            elif (spi_amp_model == "CP7164"):
                f.write("variant8.code " + str(spi_hardware_rev) + " " + str(spi_serial_number))
            elif (spi_amp_model == "CP0703"):
                f.write("variant9.code " + str(spi_hardware_rev) + " " + str(spi_serial_number))
            f.close()
        else:
            print("no need to update dsp_variant.txt")

        if(readOEM() == 0):
            if (spi_oem_code != oem_code):
                oem_need_update += 1
        else:
            oem_need_update += 1
        
        if (oem_need_update > 0):
            oem = {}
            oem["oem_label"] = ""
            oem["oem_code"] = spi_oem_code
            if (os.path.exists(oem_filename)):
                os.remove(oem_filename)
            with open(oem_filename,'w') as oem_file:
                oem_content = json.dumps(oem, indent=4)
                oem_file.write(oem_content)
        else:
            print("no need to update oem.json")

    #SPI MEMORY NO CONTENT IN IT
    else:
        print("write spi memory")
        writeSPI()

    command = "sync"
    print(command)
    os.system(command)

def main():
    if (sys.argv[1] == "check"):
        print("=> CHECK memory content and compare")
        retCompare = compare()
        if (retCompare == 0):
            print("====> SPI file check is ok !")
        elif (retCompare == 1):
            print("====> dsp variant error !")
        elif (retCompare == 2):
            print("====> oem code error !")
        elif (retCompare == 3):
            print("====> spi serial number error !")
        elif (retCompare == 4):
            print("====> spi hardware rev error !")
        elif (retCompare == 5):
            print("====> spi memory empty !")

    elif (sys.argv[1] == "read"):
        readSPIMemory()
        print("Read from SPI memory @ address " + str(address))
        read = open(spi_read_filename,'r')
        read_content = read.readlines()
        print("    " + read_content[0].rstrip('\n'))
        print("    " + read_content[1].rstrip('\n'))
        print("    " + read_content[2].rstrip('\n'))
        print("    " + read_content[3].rstrip('\n'))

    elif (sys.argv[1] == "write"):
        print("=> WRITE dsp_variant.txt to spi memory")
        retWrite = writeSPI()
        if (retWrite == 0):
            print("====> SPI Write ok !")
        elif (retWrite == 1):
            print("====> Error creating file to write")
        else:
            print("====> Error writing in spi memory")

    elif (sys.argv[1] == "restore"):
        print("=> RESTORE to dsp_variant.txt, oem.json")
        retRestore = restore()
        if (retRestore == 0):
            print("====> Restore ok !")

    elif (sys.argv[1] == "erase"):
        print("=> ERASE erase spi memory")
        eraseSPI()
    elif (sys.argv[1] == "bootcheck"):
        print("=> BOOT CHECK SEQUENCE")
        bootCheck()
    else :
        print("Please use one of the following args : check, read, write, restore, erase, bootcheck")

if __name__ == "__main__":
    main()
