]> rtime.felk.cvut.cz Git - CanFestival-3.git/blob - examples/AVR/Slave/main.c
57a74a219f874a62e4c0c3614ed938f4a6bfc3c3
[CanFestival-3.git] / examples / AVR / Slave / main.c
1 /*
2 This file is part of CanFestival, a library implementing CanOpen Stack.
3
4 Copyright (C): Edouard TISSERANT and Francis DUPIN
5 AVR Port: Andreas GLAUSER and Peter CHRISTEN
6
7 See COPYING file for copyrights details.
8
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version.
13
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 */
23 /******************************************************************************
24 Project description:
25 Test projekt for a DS 401 slave, running on Atmel's STK500 with AT90CAN128
26 Short description:
27   PORTA:        Inputs (Keys, low active)
28   PORTB:        Outputs (LEDs, low active)
29   PORTC:        Node ID (1 BCD switch)
30
31 ******************************************************************************/
32 #include "hardware.h"
33 #include "canfestival.h"
34 #include "can_AVR.h"
35 #include "objdict.h"
36 #include "ds401.h"
37
38
39 unsigned char timer_interrupt = 0;              // Set if timer interrupt eclapsed
40 unsigned char inputs;
41
42 // CAN
43 unsigned char nodeID;
44 unsigned char digital_input[1] = {0};
45 unsigned char digital_output[1] = {0};
46
47 static Message m = Message_Initializer;         // contain a CAN message
48
49 void sys_init();
50
51 // macros to handle the schedule timer
52 #define sys_timer                       timer_interrupt
53 #define reset_sys_timer()               timer_interrupt = 0
54 #define CYCLE_TIME                      1000            // Sample Timebase [us]
55
56 int main(void)
57 {
58   sys_init();                                   // Initialize system
59   canInit(CAN_BAUDRATE);                        // Initialize the CANopen bus
60   initTimer();                                  // Start timer for the CANopen stack
61   nodeID = read_bcd();                          // Read node ID first
62   setNodeId (&ObjDict_Data, nodeID);
63   setState(&ObjDict_Data, Initialisation);      // Init the state
64
65   for(;;)                                       // forever loop
66   {
67     if (sys_timer)                              // Cycle timer, invoke action on every time slice
68     {
69       reset_sys_timer();                        // Reset timer
70       digital_input[0] = get_inputs();
71       digital_input_handler(&ObjDict_Data, digital_input, sizeof(digital_input));
72       digital_output_handler(&ObjDict_Data, digital_output, sizeof(digital_output));
73       set_outputs(digital_output[0]);
74
75       // Check if CAN address has been changed
76       if(!( nodeID == read_bcd()))
77       {
78         nodeID = read_bcd();                    // Save the new CAN adress
79         setState(&ObjDict_Data, Stopped);         // Stop the node, to change the node ID
80         setNodeId(&ObjDict_Data, nodeID);         // Now the CAN adress is changed
81         setState(&ObjDict_Data, Pre_operational); // Set to Pre_operational, master must boot it again
82       }
83     }
84
85     // a message was received pass it to the CANstack
86     if (canReceive(&m))                 // a message reveived
87       canDispatch(&ObjDict_Data, &m);         // process it
88     else
89     {
90       // Enter sleep mode
91       #ifdef WD_SLEEP           // Watchdog and Sleep
92       wdt_reset();
93       sleep_enable();
94       sleep_cpu();
95       #endif                            // Watchdog and Sleep
96     }
97   }
98 }
99
100 void sys_init()
101 /******************************************************************************
102 Initialize the relays, the main states and the modbus protocol stack.
103 INPUT   LOCK_STATES *lock_states
104 OUTPUT  void
105 ******************************************************************************/
106 {
107   OSCCAL = 0x43;
108   
109   PORTA = 0xFF;                         // Inputs (Keys, low active) with pullup
110   DDRA  = 0x00;                         // 
111   PORTB = 0xFF;                         // Outputs (LEDs, low active) all 1
112   DDRB  = 0xFF;                         // 
113   PORTC = 0xFF;                         // 1 BCD switch with pullup
114   DDRC  = 0x00;                         // 
115   PORTD = 0x2C;                         // 2xCOM, unused, CAN, unused
116   DDRD  = 0x2A;                         // All init 0 or without pullup
117   PORTE = 0x00;                         // Output
118   DDRE  = 0x3C;                         // 2x not used, 2x not used
119   PORTF = 0x00;                         // Not used
120   DDRF  = 0xFF;                         // All output
121   PORTG = 0x00;                         // Not used
122   DDRG  = 0x1F;                         // Output for debug (only 5 pins)
123
124 // Set timer 0 for main schedule time
125   TCCR0A |= 1 << WGM01 | 1 << CS01 | 1 << CS00;// Timer 0 CTC , Timer 0 mit CK/64 starten
126   TIMSK0 = 1 << OCIE0A;                 // Timer Interrupts: Timer 0 Compare
127   OCR0A = (unsigned char)(F_CPU / 64 * CYCLE_TIME/1000000 - 1); // Reloadvalue for timer 0
128   #ifdef WD_SLEEP               // Watchdog and Sleep
129   wdt_reset();
130   wdt_enable(WDTO_15MS);        // Watchdogtimer start with 16 ms timeout
131   #endif                        // Watchdog and Sleep
132   sei();         // Enable Interrupts
133 }
134
135
136 #ifdef  __IAR_SYSTEMS_ICC__
137 #pragma type_attribute = __interrupt
138 #pragma vector=TIMER0_COMP_vect
139 void TIMER0_COMP_interrupt(void)
140 #else   // GCC
141 ISR(TIMER0_COMP_vect)
142 #endif  // GCC
143 /******************************************************************************
144 Interruptserviceroutine Timer 2 Compare A for the main cycle
145 ******************************************************************************/
146
147 {
148   timer_interrupt = 1;  // Set flag
149 }