src/lss.c
changeset 93 16c8ceea8f18
parent 92 0d84d95790d9
child 94 bdf4c86be6b2
--- a/src/lss.c	Tue Feb 13 17:21:19 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,740 +0,0 @@
-/*
-This file is part of CanFestival, a library implementing CanOpen Stack.
-
- Author: CANopen Canada (canfestival@canopencanada.ca)
-
-See COPYING file for copyrights details.
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include <applicfg.h>
-#include <def.h>
-
-#include <can.h>
-#include <data.h>
-#include <objdictdef.h>
-#include <objacces.h>
-#include "can_driver.h"
-
-#ifdef LED_ENABLE
-#include "led.h"
-#else
-#define led_set_state(a,b)
-#endif
-
-#include "lss.h"
-
-
-
-/*
-	NOTES
-
-	1. since in the LSS protocol all LSS Slave use the same COB, only 1 Slave
-	must be allowed to communicate with the Master
-
-	2. the Master always take the iniative. the Slave is only allowed to transmit
-	within a confirmed service
-
-	3. requesting message (from the Master) using COB-ID 2021 and response messages
-	(from the Slave) using COB-ID 2020
-*/
-
-/*
-	0 = this slave is not talking to the master
-	1 = this slave is talking to the master (this slave has been selected via )
-*/
-int	slave_selector;
-
-int	current_mode;
-
-int	lss_table_selector, lss_table_index;
-
-
-/* slave storing the information sent by the master */
-UNS32 lss_buffer[10];
-/*
-	how this buffer is used
-
-	for a SLAVE 
-	[0..3]  used to store the LSS Address
-	[4..9]  use by LSS Identify Remort Slave
-
-	for the MASTER
-	[0..3] hold the answer from the slave regarding its ID
-*/
-
-
-void lss_copy(UNS8 *data, UNS32 value)
-/* transfert 32 bits value into uns8 data vector */
-{
-	data[0] = value & 0xff;
-	data[1] = (value>>8) & 0xff;
-	data[2] = (value>>16) & 0xff;
-	data[3] = (value>>24) & 0xff;
-}
-
-
-UNS32 lss_get_value(UNS8 *data)
-/* build a 'UNS32' value from a 'unsigned char' vector */
-{
-	return data[0] + (data[1]<<8) + (data[2]<<16) + (data[3]<<24);
-}
-
-
-void lss_init_msg(Message *msg)
-{
-	msg->cob_id.w = 0;
-	msg->rtr = 0;
-	msg->len = 0;
-	msg->data[0] = 0;
-	msg->data[1] = 0;
-	msg->data[2] = 0;
-	msg->data[3] = 0;
-	msg->data[4] = 0;
-	msg->data[5] = 0;
-	msg->data[6] = 0;
-	msg->data[7] = 0;
-}
-
-
-void lss_SwitchModeGlobal(CO_Data *d, UNS32 mode)
-/*
-	this service is used to switch all LSS slaves in the network between operation
-	mode and configuration mode.
-*/
-{	
-	Message msg;
-	lss_init_msg(&msg);
-
-	/* 
-		sending a COB-ID 2021
-		[0] = 4 (for switch mode global)
-		[1] = 0 for operation mode, = 1 for configuration mode
-		[2..7] = 0 reserved
-	*/
-	
-	if (! *(d->iam_a_slave))
-	{
-		msg.cob_id.w = 0x07E5 /* 2021 */;
-
-		msg.len = 2;
-		msg.data[0] = 4;
-		msg.data[1] = (UNS8)mode;
-	
-		/* transmit */
-		(*d->canSend)(&msg);
-	}
-	else
-	{
-		/* set mode global */
-		current_mode = mode;
-	}
-}
-
-
-void lss_SwitchModeSelective_master(CO_Data *d, UNS32 *LSSaddr)
-/*
-	LSS address : <vendor-id> <product-code> <revision-number> <serial-number>
-	vendor-id : provided by CiA
-	identical to the CANopen identity object
-
-	select the slave corresponding to this ADDRESS
-*/
-{
-	Message msg;
-	lss_init_msg(&msg);
-
-	if (*(d->iam_a_slave)) /* not the master */
-		return; 
-
-	msg.cob_id.w = 0x07E5 /* 2021 */;
-	msg.len=5;
-
-	msg.data[0] = 64;
-	lss_copy(msg.data+1, LSSaddr[0]); 
-	/* transmit */
-	(*d->canSend)(&msg);
-
-	msg.data[0] = 65;
-	lss_copy(msg.data+1, LSSaddr[1]); 
-	/* transmit */
-	(*d->canSend)(&msg);
-
-	msg.data[0] = 66;
-	lss_copy(msg.data+1, LSSaddr[2]); 
-	/* transmit */
-	(*d->canSend)(&msg);
-
-	msg.data[0] = 67;
-	lss_copy(msg.data+1, LSSaddr[3]); 
-	/* transmit */
-	(*d->canSend)(&msg);
-}
-
-
-UNS32 lss_validate_address(CO_Data* d)
-{
-#if 0 
-	extern s_identity obj1018;
-
-	/* maybe we should go throught getODentry but those
-	data are 1) RO and 2) the proper ID of this device */
-#else
-	UNS32  r, vendor_id, product_code, revision_number, serial_number;
-	UNS8   sz = sizeof(UNS32), dt = int32;
-
-	r = getODentry(d, 0x1018, 1, (void *)&vendor_id, &sz, &dt, 0);
-	r = getODentry(d, 0x1018, 2, (void *)&product_code, &sz, &dt, 0);
-	r = getODentry(d, 0x1018, 3, (void *)&revision_number, &sz, &dt, 0);
-	r = getODentry(d, 0x1018, 4, (void *)&serial_number, &sz, &dt, 0);
-
-#endif
-	/*
-		if
-		lss_buffer[0] == vendor-id
-		lss_buffer[1] == product code
-		lss_buffer[2] == revision
-		lss_buffer[3] == serial
-
-		then return 1
-		else return 0;
-	*/
-
-	if (lss_buffer[0] == vendor_id  &&
-	    lss_buffer[1] == product_code &&
-	    lss_buffer[2] == revision_number &&
-	    lss_buffer[3] == serial_number)
-	{
-		return 1;
-	}
-
-	return 0;
-}
-
-
-void lss_SwitchModeSelective_slave(CO_Data *d)
-/* 
-	SwitchModeSelective for the SLAVE
-	received the frames from the master and start building 
-	the lss address 
-*/
-{
-	Message msg;
-	lss_init_msg(&msg);
-
-	/*
-		the master broadcast the address of a particular slave
-		for 64,65 and 66 store the partial address
-		when 67 arrive process the call and asknowledge if necessary
-	*/
-
-	if (lss_validate_address(d))
-	{
-		/* slave should transmit cob_id 2020  */
-		msg.cob_id.w = 0x07E4 /* 2020 */;
-
-		msg.len = 2;
-		msg.data[0] = 68;
-		msg.data[1] = (UNS8)current_mode;
-
-		/* transmit */
-		(*d->canSend)(&msg);
-	}
-
-	/* reset the address */
-	lss_buffer[0] = 0;
-	lss_buffer[1] = 0;
-	lss_buffer[2] = 0;
-	lss_buffer[3] = 0;
-}
-
-
-void lss_ConfigureNode_ID(CO_Data *d, UNS32 node_id)
-/*
-	through this service the LSS Master configures the NMT-address
-	parameter of a LSS slave.
-*/
-{
-	Message msg;
-	lss_init_msg(&msg);
-
-	if (!*(d->iam_a_slave))
-	{
-		msg.cob_id.w = 0x07E5 /* 2021 */;
-
-		msg.len = 2;
-		msg.data[0] = 17;
-		msg.data[1] = (UNS8)node_id;
-
-		/* transmit */
-		(*d->canSend)(&msg);
-	}
-	else
-	{
-		/*
-			receiving NODE ID from the master
-		*/
-
-		/*
-			error code 
-			0 = success
-			1 = node id out of range
-			2..254 = reserved
-			255 = implementation specific error occured
-				spec error = mode detailed error
-		*/
-		msg.cob_id.w = 0x07E4 /* 2020 */;
-
-		msg.len = 3;
-		msg.data[0] = 17;
-		/* msg.data[1] = error code */
-		/* msg.data[2] = spec error */
-
-		/* transmit */
-		(*d->canSend)(&msg);
-	}
-}
-
-
-void lss_ConfigureBitTimingParameters(CO_Data *d, 
-                                      UNS32 table_selector,
-                                      UNS32 table_index)
-/*
-	this service allows all LSS slaves in configuration mode.
-	must be followed by an Activate Bit Timing Parameters
-*/
-{
-	Message msg;
-	lss_init_msg(&msg);
-
-	if (!*(d->iam_a_slave))
-	{
-		msg.cob_id.w = 0x07E5 /* 2021 */;
-
-		msg.len = 3;
-		msg.data[0] = 19;
-		msg.data[1] = (UNS8)table_selector;
-		msg.data[2] = (UNS8)table_index;
-
-		/* transmit */
-		(*d->canSend)(&msg);
-	}
-	else
-	{
-		UNS8 error_code;
-
-		/* validate if this baudrate is possible */
-		if (table_selector == 0  &&  baudrate_valid(table_index) == 1)
-		{
-			lss_table_selector = table_selector;
-			lss_table_index = table_index;
-		}
-		else
-			error_code = 1; /* bit timing not supported */
-
-		msg.cob_id.w = 0x07E4 /* 2020 */;
-
-		msg.len = 3;
-		msg.data[0] = 19;
-		msg.data[1] = error_code;
-		msg.data[2] = 0;
-
-		/* transmit */
-		(*d->canSend)(&msg);
-	}
-
-	led_set_state(d, LED_AUTOBITRATE);
-}
-
-
-void lss_ActivateBitTimingParameters_master(CO_Data *d, unsigned short switch_delay)
-/*
-	switch_delay in ms
-
-	switch_delay has to be longer than the longest timeof any node
-	in the network to avoid that a node already switches while another
-	stills transmist the old bit timing parameters
-*/
-{
-	Message msg;
-	lss_init_msg(&msg);
-
-	if (*(d->iam_a_slave))
-		return;
-	
-	msg.cob_id.w = 0x07E5 /* 2021 */;
-
-	msg.len = 3;
-	msg.data[0] = 21;
-	msg.data[1] = (UNS8)(switch_delay &  0xff);
-	msg.data[2] = (UNS8)((switch_delay >> 8) & 0xff);
-
-#ifdef LED_ENABLE
-	led_set_state(LED_AUTOBITRATE);		
-#endif
-	/* transmit */
-	(*d->canSend)(&msg);
-}
-
-
-void lss_ActivateBitTimingParameters_slave(UNS8 byte_low, UNS8 byte_high)
-{
-	/* rebuild the delay value (short) from the 2 (UNS8) data */
-	unsigned short switch_delay = byte_low + (((UNS16)byte_high)<<8);
-
-	/* set the baudrate to the value proposed by the master */
-	if (lss_table_selector == 0)
-		baudrate_set(lss_table_index);
-
-	/* wait for switch_delay ms before continuing */
-}
-
-
-void lss_StoreConfiguredParameters(CO_Data *d)
-/*
-	store configured parameters into non-volatile storage
-*/
-{
-	Message msg;
-	lss_init_msg(&msg);
-
-	if (!*(d->iam_a_slave))
-	{
-		msg.cob_id.w = 0x07E5 /* 2021 */;
-
-		msg.len = 1;
-		msg.data[0] = 23;
-
-		/* transmit */
-		(*d->canSend)(&msg);
-	}
-	else
-	{
-		msg.cob_id.w = 0x07E4 /* 2020 */;
-
-		msg.data[0] = 23;
-		/* msg.data[1] = error code; */
-		/* msg.data[2] = spec err */
-		
-		/* transmit */
-		(*d->canSend)(&msg);
-	}
-}
-
-
-void lss_InquireLSSAddress_master(CO_Data *d, int flag)
-/*
-	this service allows to determine the LSS-address parameters of a LSS-slave in
-	configuration mode
-
-	request 1 single item of the LSS address
-	0 = request vendor-id
-	1 = request product-id
-	2 = request revision
-	3 = request serial
-*/
-{
-	Message msg;
-	lss_init_msg(&msg);
-
-	if (!*(d->iam_a_slave))
-	{
-		msg.cob_id.w = 0x07E5 /* 2021 */;
-
-		msg.len = 1;
-		msg.data[0] = 90 + flag;
-	
-		/* transmit */
-		(*d->canSend)(&msg);
-	}
-}
-
-
-int lss_InquireLSSAddress_slave(CO_Data *d, int cs)
-{
-	Message msg;
-	lss_init_msg(&msg);
-
-	if (!*(d->iam_a_slave)) /* not a slave */
-		return -1;
-
-	UNS32 value = 0;
-
-	switch(cs)
-	{
-		case 90:
-			value = 0; /* = vendor id */
-			break;
-		case 91:
-			value = 0; /* = product code */
-			break;
-		case 92:
-			value = 0; /* = revision */
-			break;
-		case 93:
-			value = 0; /* = serial */
-			break;
-	}
-
-	if (value > 0)
-	{
-		msg.cob_id.w = 0x07E4 /* 2020 */;
-	
-		msg.len=5;
-		msg.data[0] = cs;
-		lss_copy(msg.data+1, value);
-		
-		/* transmit */
-		(*d->canSend)(&msg);
-
-		return 0;
-	}
-
-	return -1;
-}
-
-
-void lss_IdentifyRemoteSlaves(CO_Data *d, 
-                              UNS32 vendor_id,
-                              UNS32 product_code,
-                              UNS32 rev_low,
-                              UNS32 rev_high,
-                              UNS32 serial_low,
-                              UNS32 serial_high)
-/*
-	throught this service, the LSS Master requests all LSS slave whose LSS address
-	meets the LSSaddr_sel to idenfity themselves through LSS Identify Slave
-*/
-{
-	Message msg;
-	lss_init_msg(&msg);
-
-	if (!*(d->iam_a_slave))
-	{
-		/*
-			request answers from all slaves corresponding
-			to the revision and serial range of values
-		*/
-
-		msg.cob_id.w = 0x07E5 /* 2021 */;
-		msg.len=5;
-
-		msg.data[0] = 70;
-		lss_copy(msg.data+1, vendor_id);
-		/* transmit */
-		(*d->canSend)(&msg);
-
-		msg.data[0] = 71;
-		lss_copy(msg.data+1, product_code); 
-		/* transmit */
-		(*d->canSend)(&msg);
-	
-		msg.data[0] = 72; /* revision number low */
-		lss_copy(msg.data+1, rev_low);
-		/* transmit */
-		(*d->canSend)(&msg);
-
-		msg.data[0] = 73; /* revision number high */
-		lss_copy(msg.data+1, rev_high);
-		/* transmit */
-		(*d->canSend)(&msg);
-	
-		msg.data[0] = 74; /* serial number low */
-		lss_copy(msg.data+1, serial_low);
-		/* transmit */
-		(*d->canSend)(&msg);
-
-		msg.data[0] = 75; /* serial number high */
-		lss_copy(msg.data+1, serial_high);
-		/* transmit */
-		(*d->canSend)(&msg);
-	}
-}
-
-
-int lss_validate_range_addr(CO_Data *d)
-{
-	/*
-		if 
-
-		lss_buffer[4] == vendor_id
-		lss_buffer[5] == product code
-		lss_buffer[6] <= revision <= lss_buffer[7]
-		lss_buffer[8] <= serial <= lss_buffer[9]
-
-		then return 1
-		else return 0
-	*/
-
-	UNS32  r, vendor_id, product_code, revision_number, serial_number;
-	UNS8   sz = sizeof(UNS32), dt = int32;
-
-	r = getODentry(d, 0x1018, 1, (void *)&vendor_id, &sz, &dt, 0);
-	r = getODentry(d, 0x1018, 2, (void *)&product_code, &sz, &dt, 0);
-	r = getODentry(d, 0x1018, 3, (void *)&revision_number, &sz, &dt, 0);
-	r = getODentry(d, 0x1018, 4, (void *)&serial_number, &sz, &dt, 0);
-
-	if (lss_buffer[4] == vendor_id  &&
-	    lss_buffer[5] == product_code &&
-	    lss_buffer[6] <= revision_number &&
-	    revision_number <= lss_buffer[7] &&
-	    lss_buffer[8] <= serial_number &&
-	    serial_number <= lss_buffer[9])
-	{
-		return 1;
-	}
-
-	return 0;
-}
-
-
-void lss_IdentifySlave(CO_Data *d)
-/*
-	through this service, an LSS slave indicates that it is a slave
-	with LSS address within the LSSaddr_sel
-*/
-{
-	Message msg;
-	lss_init_msg(&msg);
-
-	if (lss_validate_range_addr(d))
-	{
-		msg.cob_id.w = 0x07E4 /* 2020 */;
-
-		msg.len = 1;
-		msg.data[0] = 79;
-
-		/* transmit */
-		(*d->canSend)(&msg);
-	}
-
-	/* reset */
-	lss_buffer[4] = 0;
-	lss_buffer[5] = 0;
-	lss_buffer[6] = 0;
-	lss_buffer[7] = 0;
-	lss_buffer[8] = 0;
-	lss_buffer[9] = 0;
-}
-
-
-int lss_process_msg(CO_Data *d, Message *msg)
-{
-	/* process the incoming message */
-	if (msg->cob_id.w == 0x07E4 /* 2020 */)
-	{
-		// should be the master
-		// a slave just answered
-		switch(msg->data[0])
-		{
-			/* slave acknowledging the SwitchModeSelective call */
-			case 68: 
-				/* msg->data[1] contains the 'mode global' value from the slave*/
-				break;
-
-			/* a slave had acknowledged the call from LSS Identify Remote Slave */
-			case 79:
-				break;
-
-			/* the slave acknowledged and sent the requested data */
-			case 90:
-				lss_buffer[0] = lss_get_value(msg->data+1);
-				/* action ? */
-				break;
-			case 91:
-				lss_buffer[1] = lss_get_value(msg->data+1);
-				/* action ? */
-				break;
-			case 92:
-				lss_buffer[2] = lss_get_value(msg->data+1);
-				/* action ? */
-				break;
-			case 93:
-				lss_buffer[3] = lss_get_value(msg->data+1);
-				/* action ? */
-				break;
-		}
-	}
-
-	else if (msg->cob_id.w == 0x07E5 /* 2021 */)
-	{
-		// should be a slave
-		// the master sent a request
-		switch(msg->data[0])
-		{
-			case 4:
-				lss_SwitchModeGlobal(d, msg->data[1]);
-				break;
-
-			case 17:
-				lss_ConfigureNode_ID(d, msg->data[1]);
-				break;
-
-			case 19:
-				lss_ConfigureBitTimingParameters(d, msg->data[1], msg->data[2]);
-				break;
-			case 21:
-				lss_ActivateBitTimingParameters_slave(msg->data[1], msg->data[2]);
-				break;
-
-			/* Switch Mode Selective */
-			case 64:
-				lss_buffer[0] = lss_get_value(msg->data+1);
-				break;
-			case 65:
-				lss_buffer[1] = lss_get_value(msg->data+1);
-				break;
-			case 66:
-				lss_buffer[2] = lss_get_value(msg->data+1);
-				break;
-			case 67:
-				lss_buffer[3] = lss_get_value(msg->data+1);
-				lss_SwitchModeSelective_slave(d);
-				break;
-
-			/* Identify Remote Slave */
-			case 70:
-				lss_buffer[4] = lss_get_value(msg->data+1);
-				break;
-			case 71:
-				lss_buffer[5] = lss_get_value(msg->data+1);
-				break;
-			case 72:
-				lss_buffer[6] = lss_get_value(msg->data+1);
-				break;
-			case 73:
-				lss_buffer[7] = lss_get_value(msg->data+1);
-				break;
-			case 74:
-				lss_buffer[8] = lss_get_value(msg->data+1);
-				break;
-			case 75:
-				lss_buffer[9] = lss_get_value(msg->data+1);
-				lss_IdentifySlave(d);
-				break;
-
-			/* Inquire Identify of Slave */
-			case 90:
-			case 91:
-			case 92:
-			case 93:
-				lss_InquireLSSAddress_slave(d, msg->data[0]);
-				break;
-		}
-	}
-
-	return 0;
-}