##
# @file    main.py
# @brief   Example of a CAN Display
# @version 1.0
#

import can
import gui

# Functions and constants ######################################################
value1 = ['----']
value2 = ['----']
value3 = ['----']
value4 = ['----']

# This callback is called everytime the screen refreshes (60Hz)
def vsync_cb(l):
    gui.redraw() 

# Helper function to convert bytes to an int
def bytes_to_int(bytes):
    result = 0
    for b in bytes:
        result = result * 256 + int(b)
    return result

# Function to process the CAN data
def handle_can(bus):  
    while True:
        can_msg = can.get_msg(bus)
        if can_msg is None:
            return
        if can_msg.id == 0x301:
            value1[0] = "{:02}".format(can_msg.data[0])
        elif can_msg.id == 0x302:
            value2[0] = "{:06.2f}Km/h".format(bytes_to_int(can_msg.data[4:6])*0.0182)
            value3[0] = "{:06.2f}".format(bytes_to_int(can_msg.data[6:])*0.01)
        elif can_msg.id == 0x303:
            value4[0] = "{:06.2f}m".format(int.from_bytes(bytes(can_msg.data[:3]), "big", True)*0.01) 

# This callback is called every time a CAN message is received on CAN0
def can0_cb():
    handle_can(can.CAN0)

# This callback is called every time a CAN message is received on CAN1
def can1_cb():
    handle_can(can.CAN1)

# Main #########################################################################
def main():
    # Initialization of CAN1 at 500kbps ########################################
    can.reset(can.CAN1, 500000)
    # Set up CAN callback
    can.set_callback(can.CAN1, can1_cb)
    #Turn on Termination
    can.termination(can.CAN1, True)
    #Listen on all ids
    #can.add_rx_id(can.CAN1,0,0)
    #Listen on specific ids only
    can.add_rx_id(can.CAN1, 0x301)
    can.add_rx_id(can.CAN1, 0x302)
    can.add_rx_id(can.CAN1, 0x303)
    # Disable CAN test mode
    can.test_mode(can.CAN1, 0)
     
    # Initialization of CAN0 at 500kbps ########################################
    can.reset(can.CAN0, 500000)
    # Set up CAN callback
    can.set_callback(can.CAN0, can0_cb)
    #Turn on Termination
    can.termination(can.CAN0, True)
    #Listen on all ids
    #can.add_rx_id(can.CAN0,0,0)
    #Listen on specific ids only
    can.add_rx_id(can.CAN0, 0x301)
    can.add_rx_id(can.CAN0, 0x302)
    can.add_rx_id(can.CAN0, 0x303)
    # Disable CAN test mode
    can.test_mode(can.CAN0, 0)

    # List of items to pass to the gui
    gui_l = [
        [gui.EVT_VSYNC, vsync_cb],  
        [gui.DL_SAVE_CONTEXT()],
        [gui.DL_CLEAR_COLOR_RGB(0, 41, 66)],
        [gui.DL_CLEAR(1, 1, 1)],
        [gui.DL_SCISSOR_SIZE(800, 350)],
        [gui.DL_SCISSOR_XY(0, 65)],
        [gui.DL_CLEAR_COLOR_RGB(255, 255, 255)],
        [gui.DL_CLEAR(1, 1, 1)],
        [gui.DL_RESTORE_CONTEXT()],
        [gui.DL_COLOR_RGB(255, 255, 255)],
        [gui.CTRL_TEXT, 30, 7, 31, 0, 'CAN Display Example'],  
        [gui.DL_COLOR_RGB(0, 0, 0)],    
        [gui.CTRL_TEXT, 200, 90, 31, gui.OPT_CENTERX,'Satellites'],
        [gui.CTRL_TEXT, 200, 160, 32, gui.OPT_CENTERX,value1],
        [gui.CTRL_TEXT, 600, 90, 31, gui.OPT_CENTERX,'Speed'],
        [gui.CTRL_TEXT, 600, 160, 32, gui.OPT_CENTERX,value2],
        [gui.CTRL_TEXT, 200, 270, 31, gui.OPT_CENTERX,'Heading'],
        [gui.CTRL_TEXT, 200, 340, 32, gui.OPT_CENTERX,value3],
        [gui.CTRL_TEXT, 600, 270, 31, gui.OPT_CENTERX,'Altitude'],
        [gui.CTRL_TEXT, 600, 340, 32, gui.OPT_CENTERX,value4],
    ]
    gui.show(gui_l)

if __name__ == '__main__':
    main()