/*
 * Main.c
 *
 *  Created on: 16 juli 2021
 *      Author: Daniel Mårtensson
 */

#include <stdio.h>

 /* Include Open SAE J1939 */
#include "Open_SAE_J1939/Open_SAE_J1939.h"

int main() {

	/* Create our J1939 structure with two ECU */
	J1939 j1939_1 = { 0 };
	J1939 j1939_2 = { 0 };

	/* Important to sent all non-address to 0xFF - Else we cannot use ECU address 0x0 */
	uint8_t i;
	for (i = 0; i < 255; i++) {
		j1939_1.other_ECU_address[i] = 0xFF;
		j1939_2.other_ECU_address[i] = 0xFF;
	}

	/* Set the ECU address */
	j1939_1.information_this_ECU.this_ECU_address = 0x80;												/* From 0 to 253 because 254 = error address and 255 = broadcast address */
	j1939_2.information_this_ECU.this_ECU_address = 0x90;

	/* Set NAME for ECU 1 */
	j1939_1.information_this_ECU.this_name.identity_number = 100; 										/* From 0 to 2097151 */
	j1939_1.information_this_ECU.this_name.manufacturer_code = 300; 									/* From 0 to 2047 */
	j1939_1.information_this_ECU.this_name.function_instance = 10; 										/* From 0 to 31 */
	j1939_1.information_this_ECU.this_name.ECU_instance = 2; 											/* From 0 to 7 */
	j1939_1.information_this_ECU.this_name.function = FUNCTION_VDC_MODULE;								/* From 0 to 255 */
	j1939_1.information_this_ECU.this_name.vehicle_system = 100;										/* From 0 to 127 */
	j1939_1.information_this_ECU.this_name.arbitrary_address_capable = 0;								/* From 0 to 1 */
	j1939_1.information_this_ECU.this_name.industry_group = INDUSTRY_GROUP_CONSTRUCTION;				/* From 0 to 7 */
	j1939_1.information_this_ECU.this_name.vehicle_system_instance = 10;								/* From 0 to 15 */

	/* Set NAME for ECU 2 */
	j1939_2.information_this_ECU.this_name.identity_number = 1000; 										/* From 0 to 2097151 */
	j1939_2.information_this_ECU.this_name.manufacturer_code = 400; 									/* From 0 to 2047 */
	j1939_2.information_this_ECU.this_name.function_instance = 20; 										/* From 0 to 31 */
	j1939_2.information_this_ECU.this_name.ECU_instance = 1; 											/* From 0 to 7 */
	j1939_2.information_this_ECU.this_name.function = FUNCTION_VDC_MODULE;								/* From 0 to 255 */
	j1939_2.information_this_ECU.this_name.vehicle_system = 50;											/* From 0 to 127 */
	j1939_2.information_this_ECU.this_name.arbitrary_address_capable = 0;								/* From 0 to 1 */
	j1939_2.information_this_ECU.this_name.industry_group = INDUSTRY_GROUP_GLOBAL;						/* From 0 to 7 */
	j1939_2.information_this_ECU.this_name.vehicle_system_instance = 10;								/* From 0 to 15 */

	/* First let ECU 1 and ECU 2 know each other - This should be done at the startup of every ECU */
	SAE_J1939_Response_Request_Address_Claimed(&j1939_1);
	SAE_J1939_Response_Request_Address_Claimed(&j1939_2);

	/* Let ECU 2 read and then ECU 1 */
	Open_SAE_J1939_Listen_For_Messages(&j1939_2);
	Open_SAE_J1939_Listen_For_Messages(&j1939_1);

	/* Print information */
	printf("How many external ECU are connected according to ECU 1: %i and the NAME came from address = 0x%x\n", j1939_1.number_of_other_ECU, j1939_1.from_other_ecu_name.from_ecu_address);
	printf("How many external ECU are connected according to ECU 2: %i and the NAME came from address = 0x%x\n", j1939_2.number_of_other_ECU, j1939_2.from_other_ecu_name.from_ecu_address);

	/* Set NAME for ECU 2 by using Commanded Address. Also change the ECU address from 0x90 to 0x91 */
	uint8_t DA = 0x90; /* Change this to broadcast address 0xFF */
	SAE_J1939_Send_Commanded_Address(&j1939_1, DA, 0x91, 5000, 500, 30, 5, FUNCTION_AUXILIARY_VALVES_CONTROL, 50, 0, INDUSTRY_GROUP_AGRICULTURAL_AND_FORESTRY, 15);

	/* Listen for messages - The reason why it looks like this is because ECU 1 and ECU 2 shares the same CAN-bus buffer - In CAN bus application, you don't need this mess */
	if (DA == 0xFF) {
		Open_SAE_J1939_Listen_For_Messages(&j1939_2);
		Open_SAE_J1939_Listen_For_Messages(&j1939_2);
		Open_SAE_J1939_Listen_For_Messages(&j1939_2);
		Open_SAE_J1939_Listen_For_Messages(&j1939_2);
		Open_SAE_J1939_Listen_For_Messages(&j1939_2);
		Open_SAE_J1939_Listen_For_Messages(&j1939_2);
	}
	else {
		Open_SAE_J1939_Listen_For_Messages(&j1939_2); /* Read TP CM with control byte RTS from ECU 1 to ECU 2 */
		Open_SAE_J1939_Listen_For_Messages(&j1939_1); /* Read control byte CTS response from ECU 2 */
		Open_SAE_J1939_Listen_For_Messages(&j1939_2); /* Read TP DT package 1 from ECU 1 */
		Open_SAE_J1939_Listen_For_Messages(&j1939_1); /* Read TP DT package 2 from ECU 1 */
		Open_SAE_J1939_Listen_For_Messages(&j1939_2); /* Read one more package */
		Open_SAE_J1939_Listen_For_Messages(&j1939_1); /* Read the send request of delete address from ECU 2 */
		Open_SAE_J1939_Listen_For_Messages(&j1939_2); /* Read the new address from ECU 2 */
		Open_SAE_J1939_Listen_For_Messages(&j1939_1); /* Read the send request of delete address from ECU 2 */
		Open_SAE_J1939_Listen_For_Messages(&j1939_2); /* Read the new address from ECU 2 */
	}
	/* Print information */
	printf("Identity number = %i\nManufacturer code = %i\nFunction instance = %i\nECU instance = %i\nFunction = %i\nVehicle system = %i\nArbitrary address capable = %i\nIndustry group = %i\nVehicle system instance = %i\nNew ECU address = 0x%X\n"
		, j1939_2.information_this_ECU.this_name.identity_number
		, j1939_2.information_this_ECU.this_name.manufacturer_code
		, j1939_2.information_this_ECU.this_name.function_instance
		, j1939_2.information_this_ECU.this_name.ECU_instance
		, j1939_2.information_this_ECU.this_name.function
		, j1939_2.information_this_ECU.this_name.vehicle_system
		, j1939_2.information_this_ECU.this_name.arbitrary_address_capable
		, j1939_2.information_this_ECU.this_name.industry_group
		, j1939_2.information_this_ECU.this_name.vehicle_system_instance
		, j1939_2.information_this_ECU.this_ECU_address);

	printf("How many external ECU are connected according to ECU 1: %i and the NAME came from address = 0x%X\n", j1939_1.number_of_other_ECU, j1939_1.from_other_ecu_name.from_ecu_address);
	printf("How many external ECU are connected according to ECU 2: %i and the NAME came from address = 0x%X (0xFE is error address)\n", j1939_2.number_of_other_ECU, j1939_2.from_other_ecu_name.from_ecu_address);

	return 0;
}
