--- 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;
-}