examples/AVR/DS401_Slave/main.c
changeset 375 03fb0bfccc1f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/AVR/DS401_Slave/main.c	Thu Jan 31 15:20:59 2008 +0100
@@ -0,0 +1,158 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+
+Copyright (C): Edouard TISSERANT and Francis DUPIN
+AVR Port: Andreas GLAUSER and Peter CHRISTEN
+
+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
+*/
+/******************************************************************************
+Project description:
+Test projekt for a DS 401 slave, running on Atmel's STK500 with AT90CAN128
+Short description:
+  PORTA:	Inputs (Keys, low active)
+  PORTB:	Outputs (LEDs, low active)
+  PORTC:	Node ID (1 BCD switch)
+
+******************************************************************************/
+#include "hardware.h"
+#include "canfestival.h"
+#include "can_AVR.h"
+#include "objdict.h"
+
+unsigned char timer_interrupt = 0;		// Set if timer interrupt eclapsed
+unsigned char inputs;
+
+// CAN
+unsigned char nodeID;
+static Message m = Message_Initializer;		// contain a CAN message
+
+static unsigned char old_input_value;		// Inputs, to check if a input has changed
+
+void sys_init();
+
+// macros to handle the schedule timer
+#define sys_timer			timer_interrupt
+#define reset_sys_timer()		timer_interrupt = 0
+#define CYCLE_TIME	        	1000     	// Sample Timebase [us]
+
+int main(void)
+{
+  sys_init();                                   // Initialize system
+  canInit(CAN_BAUDRATE);         		// Initialize the CANopen bus
+  initTimer();                                 	// Start timer for the CANopen stack
+  nodeID = read_bcd();				// Read node ID first
+  setNodeId (&ObjDict_Data, nodeID);
+  setState(&ObjDict_Data, Initialisation);	// Init the state
+  PDOInit(&ObjDict_Data);
+
+  // Examples for callbacks
+  // RegisterSetODentryCallBack(d, 0x1005, 0, &OnCOB_ID_SyncUpdate);
+  // errorCode = setODentry(d, d->transfers[line].index, d->transfers[line].subIndex, 
+  // (void *) d->transfers[line].data, &size, 1);
+
+  for(;;)		                        // forever loop
+  {
+    if (sys_timer)	                        // Cycle timer, invoke action on every time slice
+    {
+      reset_sys_timer();	                // Reset timer
+
+      // Read the input states from the ports
+      Read_Inputs_8_Bit[0]  = get_inputs();
+      // Send the new input state if there was a change
+      if (old_input_value != Read_Inputs_8_Bit[0])
+      {
+          old_input_value = Read_Inputs_8_Bit[0];
+	  if (getState(&ObjDict_Data) == Operational)
+	    sendPDOevent(&ObjDict_Data);
+      }
+      set_outputs(Write_Outputs_8_Bit[0]);
+
+      // Check if CAN address has been changed
+      if(!( nodeID == read_bcd()))
+      {
+        nodeID = read_bcd();                    // Save the new CAN adress
+        setState(&ObjDict_Data, Stopped);         // Stop the node, to change the node ID
+        setNodeId(&ObjDict_Data, nodeID);         // Now the CAN adress is changed
+        setState(&ObjDict_Data, Pre_operational); // Set to Pre_operational, master must boot it again
+      }
+    }
+    // Handle all MOB's at once, if a message was received pass it to the CANstack
+    if (canReceive(&m))			// a message reveived
+      canDispatch(&ObjDict_Data, &m);         // process it
+    else
+    {
+      // Enter sleep mode
+      #ifdef WD_SLEEP		// Watchdog and Sleep
+      wdt_reset();
+      sleep_enable();
+      sleep_cpu();
+      #endif				// Watchdog and Sleep
+    }
+  }
+}
+
+void sys_init()
+/******************************************************************************
+Initialize the relays, the main states and the modbus protocol stack.
+INPUT	LOCK_STATES *lock_states
+OUTPUT	void
+******************************************************************************/
+{
+  OSCCAL = 0x43;
+  
+  PORTA = 0xFF;	                        // Inputs (Keys, low active) with pullup
+  DDRA  = 0x00;		                // 
+  PORTB = 0xFF;	                        // Outputs (LEDs, low active) all 1
+  DDRB  = 0xFF;		                // 
+  PORTC = 0xFF;	                        // 1 BCD switch with pullup
+  DDRC  = 0x00;		                // 
+  PORTD = 0x2C;	                        // 2xCOM, unused, CAN, unused
+  DDRD  = 0x2A;		                // All init 0 or without pullup
+  PORTE = 0x00;	                        // Output
+  DDRE  = 0x3C;		                // 2x not used, 2x not used
+  PORTF = 0x00;	                        // Not used
+  DDRF  = 0xFF;		                // All output
+  PORTG = 0x00;	                        // Not used
+  DDRG  = 0x1F;		                // Output for debug (only 5 pins)
+
+// Set timer 0 for main schedule time
+  TCCR0A |= 1 << WGM01 | 1 << CS01 | 1 << CS00;// Timer 0 CTC , Timer 0 mit CK/64 starten
+  TIMSK0 = 1 << OCIE0A;		        // Timer Interrupts: Timer 0 Compare
+  OCR0A = (unsigned char)(F_CPU / 64 * CYCLE_TIME/1000000 - 1);	// Reloadvalue for timer 0
+  #ifdef WD_SLEEP		// Watchdog and Sleep
+  wdt_reset();
+  wdt_enable(WDTO_15MS);   	// Watchdogtimer start with 16 ms timeout
+  #endif			// Watchdog and Sleep
+  sei();         // Enable Interrupts
+}
+
+
+#ifdef  __IAR_SYSTEMS_ICC__
+#pragma type_attribute = __interrupt
+#pragma vector=TIMER0_COMP_vect
+void TIMER0_COMP_interrupt(void)
+#else	// GCC
+ISR(TIMER0_COMP_vect)
+#endif	// GCC
+/******************************************************************************
+Interruptserviceroutine Timer 2 Compare A for the main cycle
+******************************************************************************/
+
+{
+  timer_interrupt = 1;	// Set flag
+}