diff options
author | Yves Fischer <yvesf-git@xapek.org> | 2011-10-13 20:33:30 +0200 |
---|---|---|
committer | Yves Fischer <yvesf-git@xapek.org> | 2011-10-13 20:33:30 +0200 |
commit | 5d9d373a959271b498710817d08c2ea8e153aa6e (patch) | |
tree | 6867e887454a850b4e15616000ef342a1c661c7e /firmware/can.c | |
parent | 35a36b0a6c69ce136fd6ea2a203d34e48e1291e8 (diff) | |
download | mini-octopus-5d9d373a959271b498710817d08c2ea8e153aa6e.tar.gz mini-octopus-5d9d373a959271b498710817d08c2ea8e153aa6e.zip |
correct firmware??
Diffstat (limited to 'firmware/can.c')
-rw-r--r-- | firmware/can.c | 756 |
1 files changed, 0 insertions, 756 deletions
diff --git a/firmware/can.c b/firmware/can.c deleted file mode 100644 index 95090bb..0000000 --- a/firmware/can.c +++ /dev/null @@ -1,756 +0,0 @@ -/* - * Copyright (c) 2007 Marco Glietsch (http://www.mikrocontroller.net/topic/98697) - * Original author: Marco Glietsch - * Modified for octopus by Michael Hartmann <ich@speicherleck.de> - * All rights reserved. - * - * Short descripton of file: - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of the FH Augsburg nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES{} LOSS OF USE, - * DATA, OR PROFITS{} OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifdef __AVR_AT90CAN128__ - -#include "common.h" -#include "protocol.h" -#include "can.h" - -#include <avr/io.h> -#include <avr/interrupt.h> -#include <util/delay.h> -#include <inttypes.h> -#include <stdbool.h> - -struct { - uint32_t id; - int8_t data[8]; -} message; - -int8_t iemob[15] = { - IEMOB0, IEMOB1, IEMOB2, IEMOB3, IEMOB4, IEMOB5, IEMOB6, IEMOB7, - IEMOB8, IEMOB9, IEMOB10, IEMOB11, IEMOB12, IEMOB13, IEMOB14 }; - -// extended id -int8_t extended_id; - -void can_parser(uint8_t *buf) -{ - switch(buf[0]) - { - case CMD_CAN_INIT: - can_init_usb((uint8_t)buf[2], (uint8_t)buf[3]); - break; - case CMD_CAN_DEINIT: - can_deinit_usb(); - break; - case CMD_CAN_ENABLE_MOB: - asm("nop"); - uint32_t idm = 0; - uint32_t id = 0; - - id = ((uint32_t)buf[4]) + - ((uint32_t)buf[5] << 8) + - ((uint32_t)buf[6] << 16) + - ((uint32_t)buf[7] << 24); - - idm = ((uint32_t)buf[8]) + - ((uint32_t)buf[9] << 8) + - ((uint32_t)buf[10] << 16) + - ((uint32_t)buf[11] << 24); - - // mob, mode, id, idm - can_enable_mob_usb(buf[2], buf[3], id, idm); - break; - case CMD_CAN_DISABLE_MOB: - can_disable_mob_usb((uint8_t)buf[2]); - break; - case CMD_CAN_SEND_DATA: - can_send_data_usb(buf[2], buf[3], &buf[4]); - break; - case CMD_CAN_SEND_REMOTE: - can_send_remote_usb(buf[2]); - break; - case CMD_CAN_RECEIVE_DATA: - can_receive_data_usb(buf[2]); - break; - case CMD_CAN_SET_AUTOREPLY: - can_set_autoreply_usb(buf[2], buf[3], &buf[4]); - break; - default: - answer[0] = buf[0]; - answer[1] = RSP_UNKOWN_CMD; - answer[2] = 0; - CommandAnswer(3); - } -} - -void can_init_usb(uint8_t baudrate, uint8_t eid) -{ - answer[0] = CMD_CAN_INIT; - answer[1] = (uint8_t)can_init(baudrate, CAN_INTERRUPTS_RX, eid); - answer[2] = 0; - - CommandAnswer(3); -} - -// Message Objects zuruecksetzen, CAN-Controller aktivieren -// Parameter: -// uint8_t baud: 0,1,2...5 (fuer 100, 125, 200, 250, 500, 1000) -// uint8_t intmode: Ereignis, bei dem ein Interrupt ausgelöst werden soll -// - NONE - Deaktiviert -// - TX - Daten gesendet -// - RX - Daten empfangen -// - TXRX - Daten gesendet und/oder empfangen -int can_init(uint8_t baudrate, uint8_t intmode, uint8_t eid) -{ - uint8_t i; - - octopus.ports[17] = PIN_CAN; - octopus.ports[18] = PIN_CAN; - - extended_id = eid ? 1 : 0; - - message.id = 0; - for(i = 0; i < 8; i++) - message.data[i] = 0; - - // Status- und Steuerregister aller Message Objects initialisieren - for(i = 0; i < NO_MOBS; i++) - { - can_get_mob(i); - CANSTMOB = 0; - CANCDMOB = 0; - } - - // set baudrate - if(can_set_baudrate(baudrate) == 0) - return RSP_ERROR; - - if(can_set_interrupt(intmode) == 0) - return RSP_ERROR; - - // CAN-Controller in Enabled Mode setzen - setbit(CANGCON, ENASTB); - - // Warten bis der CAN-Controller das Enabled-Bit gesetzt hat und - // einsatzbereit ist - while (!getbit(CANGSTA, ENFG)); - - return RSP_OK; -} - -void can_deinit_usb(void) -{ - answer[0] = CMD_CAN_DEINIT; - answer[1] = (int8_t)can_deinit(); - answer[2] = 0; - - CommandAnswer(3); -} - -int can_deinit(void) -{ - uint8_t i; - - octopus.ports[17] = PIN_NONE; - octopus.ports[18] = PIN_NONE; - - for(i = 0; i < 15; i++) - can_disable_mob(i); - - // CAN-Controller ausschalten - clearbit(CANGCON, ENASTB); - - // warten bis wirklich ausgechaltet - while (getbit(CANGSTA, ENFG)); - - return RSP_OK; -} - -void can_set_autoreply(uint8_t mob, uint8_t length, uint8_t *buf) -{ - can_get_mob(mob); - can_set_mode(CAN_MODE_AUTO_REPLY); - can_set_data(length, buf); -} - -void can_set_autoreply_usb(uint8_t mob, uint8_t length, uint8_t *buf) -{ - can_set_autoreply(mob, length, buf); - - answer[0] = CMD_CAN_SET_AUTOREPLY; - answer[1] = RSP_OK; - answer[2] = 0; - - CommandAnswer(3); -} - -int can_set_baudrate(uint8_t baudrate) -{ - // @16 MHz - switch(baudrate) - { - case CAN_BAUDRATE_100K: - CANBT1 = 0x12; - CANBT2 = 0x0c; - CANBT3 = 0x37; - break; - - case CAN_BAUDRATE_125K: - CANBT1 = 0x0e; - CANBT2 = 0x0c; - CANBT3 = 0x37; - break; - - case CAN_BAUDRATE_200K: - CANBT1 = 0x08; - CANBT2 = 0x0c; - CANBT3 = 0x37; - break; - - case CAN_BAUDRATE_250K: - CANBT1 = 0x06; - CANBT2 = 0x0c; - CANBT3 = 0x37; - break; - - case CAN_BAUDRATE_500K: - CANBT1 = 0x02; - CANBT2 = 0x0c; - CANBT3 = 0x37; - break; - - case CAN_BAUDRATE_1000K: - CANBT1 = 0x00; - CANBT2 = 0x0c; - CANBT3 = 0x37; - break; - - default: - return 0; - } - - return 1; -} - -void can_enable_mob_usb(uint8_t mob, uint8_t mode, uint32_t id, uint32_t idm) -{ - answer[0] = CMD_CAN_ENABLE_MOB; - answer[1] = (int8_t)can_enable_mob(mob, mode, id, idm); - answer[2] = 0; - - CommandAnswer(3); -} - - -// Parameter: -// uint8_t mob: Nummer des zu wählenden Objekts (0-14) -// -// uint8_t mode -// - Betriebsart des Message Objekts: -// - DISABLED Deaktiviert -// - TRANSMIT_DATA Daten senden -// - TRANSMIT_REMOTE Anfrage senden -// - RECEIVE_DATA Empfangsmodus -// - AUTO_REPLY automatischer Antwortmodus -// -// Funktion setzt die Betriebsart des vorher gewählten Objekts -int can_enable_mob(uint8_t mob, uint8_t mode, uint32_t id, uint32_t idm) -{ - // Objekt wählen - can_get_mob(mob); - - // Interrupt für dieses Objekt aktivieren - can_set_mob_interrupt(mob); - - // ID-Maske setzen - can_set_id_mask(idm); - - // ID setzen - can_set_id(id); - - // Betriebsmodus setzen - if(can_set_mode(mode) == 0) - return RSP_ERROR; - - return RSP_OK; -} - - -void can_send_data_usb(uint8_t mob, uint8_t length, uint8_t *data) -{ - answer[0] = CMD_CAN_SEND_DATA; - answer[1] = (int8_t)can_send_data(mob, length, data); - answer[2] = 0; - - CommandAnswer(3); -} - -int can_send_data(uint8_t mob, uint8_t length, uint8_t * data) -{ - uint8_t mode; - - // Objekt wählen - can_get_mob(mob); - - // Aktuelle Betriebsart sichern - mode = can_get_mode(); - - // Nutzdaten in Register schreiben - can_set_data(length, data); - - // Datenübertragung starten - can_set_mode(CAN_MODE_TRANSMIT_DATA); - - // Warten bis die Datenübertragung beendet ist (TXOK-Flag von CAN-Controller - // gesetzt) - while (!getbit(CANSTMOB, TXOK)); - - // TXOK-Flag von Hand löschen - clearbit(CANSTMOB, TXOK); - - // Alte Betriebsart wiederherstellen - can_set_mode(mode); - - return RSP_OK; -} - - -// Parameter: uint8_t mode: Ereignis, bei dem Interrupt ausgelöst werden soll -// - NONE - Deaktiviert -// - TX - Daten gesendet -// - RX - Daten empfangen -// - TXRX - Daten gesendet und/oder empfangen -int can_set_interrupt(uint8_t mode) -{ - switch(mode) - { - case CAN_INTERRUPTS_NONE: - clearbit(CANGIE, ENIT); - clearbit(CANGIE, ENRX); - clearbit(CANGIE, ENTX); - break; - - case CAN_INTERRUPTS_TX: - setbit(CANGIE, ENIT); - clearbit(CANGIE, ENRX); - setbit(CANGIE, ENTX); - break; - - case CAN_INTERRUPTS_RX: - setbit(CANGIE, ENIT); - setbit(CANGIE, ENRX); - clearbit(CANGIE, ENTX); - break; - - case CAN_INTERRUPTS_TXRX: - setbit(CANGIE, ENIT); - setbit(CANGIE, ENRX); - setbit(CANGIE, ENTX); - break; - - default: - return 0; - } - - return 1; -} - - -// Funktion wählt CANPAGE des betreffenden Objekts aus und stellt Zugang zu -// Registern des Objekts her -void can_get_mob(uint8_t mob) -{ - CANPAGE = (mob << 4); -} - - -// Parameter: uint32_t idm: ID-Maske in Dezimalschreibweise -// Funktion setzt ID-Maske eines Objekts auf einen neuen Wert. In CANIDM4 -// bleiben dabei die Werte der unteren 3 Bit (RTRTAG, Reserved und IDEMSK) -// erhalten. -void can_set_id_mask(uint32_t idm) -{ - //Standart identifier (11 bit) - if(!extended_id) - { - CANIDM2 = (uint8_t)(idm << 5); - CANIDM1 = (uint8_t)(idm >> 3); - } - //extended identifier - else - { - idm <<= 3; - idm |= 7; - - CANIDM4 = (int8_t) (idm); - CANIDM3 = (int8_t) (idm>>8); - CANIDM2 = (int8_t) (idm>>16); - CANIDM1 = (int8_t) (idm>>24); - } -} - -// Funktion holt ID der empfangenen Nachricht -uint32_t can_get_id(void) -{ - uint32_t id = 0; - - //Standart identifier (11 bit) - if(!extended_id) - { - id = (uint8_t) CANIDT2 >> 5; - id |= (uint16_t) CANIDT1 << 3; - } - //extended identifier - else - { - id |= ((uint32_t) CANIDT1 << 24); - id |= ((uint32_t) CANIDT2 << 16); - id |= ((uint32_t) CANIDT3 << 8); - id |= (CANIDT4&0xF8); - id >>= 3; - } - - return id; -} - -// Funktion setzt ID eines Objekts auf einen neuen Wert. In CANIDM4 bleiben -// dabei die Werte der unteren 3 Bit (RTRTAG, RB1TAG und RB0TAG) erhalten. -void can_set_id(uint32_t id) -{ - //Standart identifier (11 bit) - if(!extended_id) - { - CANIDT2 = (uint8_t)(id << 5); - CANIDT1 = (uint8_t)(id >> 3); - } - //extended identifier - else - { - id <<= 3; - id &= 0xfffffff8; - id |= (CANIDT4 & 0x07); - - CANIDT4 = (int8_t) (id); - CANIDT3 = (int8_t) (id>>8); - CANIDT2 = (int8_t) (id>>16); - CANIDT1 = (int8_t) (id>>24); - } -} - - -// Funktion setzt die Betriebsart des vorher gewählten Objekts. -// Parameter: uint8_t mode: -// - Betriebsart des Message Objekts: -// - DISABLED - Deaktiviert -// - TRANSMIT_DATA - Daten senden -// - TRANSMIT_REMOTE - Anfrage senden -// - RECEIVE_DATA - Empfangsmodus -// - AUTO_REPLY - automatischer Antwortmodus -int can_set_mode(uint8_t mode) -{ - if(extended_id) - setbit(CANCDMOB, IDE); - else - clearbit(CANCDMOB, IDE); - - switch(mode) - { - case CAN_MODE_DISABLED: - clearbit(CANCDMOB, CONMOB0); - clearbit(CANCDMOB, CONMOB1); - clearbit(CANCDMOB, RPLV); - clearbit(CANIDT4, RTRTAG); - clearbit(CANIDM4, RTRMSK); - break; - - case CAN_MODE_TRANSMIT_DATA: - CANCDMOB &= ~(1 << CONMOB1 || 1 << CONMOB0 || 1 << RPLV); - CANCDMOB |= (1 << CONMOB0 || 0 << CONMOB1); - clearbit(CANIDT4, RTRTAG); - break; - - case CAN_MODE_TRANSMIT_REMOTE: - clearbit(CANCDMOB, CONMOB1); - setbit(CANCDMOB, CONMOB0); - clearbit(CANCDMOB, RPLV); - setbit(CANIDT4, RTRTAG); - break; - - case CAN_MODE_RECEIVE_DATA: - clearbit(CANCDMOB, CONMOB0); - setbit(CANCDMOB, CONMOB1); - clearbit(CANCDMOB, RPLV); - clearbit(CANIDT4, RTRTAG); - break; - - case CAN_MODE_AUTO_REPLY: - clearbit(CANCDMOB, CONMOB0); - setbit(CANCDMOB, CONMOB1); - setbit(CANCDMOB, RPLV); - setbit(CANIDT4, RTRTAG); - break; - - default: - return 0; - } - - return 1; -} - - -// Funktion holt die Betriebsart des vorher gewaehlten Objekts -uint8_t can_get_mode(void) -{ - uint8_t mode = 0; - - if(!getbit(CANCDMOB, CONMOB1) && !getbit(CANCDMOB, CONMOB0)) - { - mode = CAN_MODE_DISABLED; - } - else if(!getbit(CANCDMOB, CONMOB1) && getbit(CANCDMOB, CONMOB0) && - !getbit(CANIDT4, RTRTAG)) - { - mode = CAN_MODE_TRANSMIT_DATA; - } - else if(!getbit(CANCDMOB, CONMOB1) && getbit(CANCDMOB, CONMOB0) && - getbit(CANIDT4, RTRTAG)) - { - mode = CAN_MODE_TRANSMIT_REMOTE; - } - else if(getbit(CANCDMOB, CONMOB1) && !getbit(CANCDMOB, CONMOB0) && - !getbit(CANIDT4, RTRTAG)) - { - mode = CAN_MODE_RECEIVE_DATA; - } - else if(getbit(CANCDMOB, CONMOB1) && !getbit(CANCDMOB, CONMOB0) && - getbit(CANCDMOB,RPLV) && getbit(CANIDT4, RTRTAG)) - { - mode = CAN_MODE_AUTO_REPLY; - } - - return mode; -} - - -// Funktion schreibt in das Objekt die zu uebermittelnden Daten -void can_set_data(uint8_t length, uint8_t * data) -{ - uint8_t i; - uint8_t cancdmob; - - if(length > 8) - length = 8; - - // Anzahl der Datenbytes in der Nachricht - // scheinbar darf man das CANCDMOB register nicht beliebig oft - // schreiben/lesen, daher speichern wir den wert dazwischen, loeschen die - // entsprechenden bits fuer die laenge und schreiben dann unsere laenge rein - // wie dem auch sei: so funktionierts zumindest, also vorsicht beim aufraeumen ;-) - cancdmob = CANCDMOB; - clearbit(cancdmob, DLC0); - clearbit(cancdmob, DLC1); - clearbit(cancdmob, DLC2); - clearbit(cancdmob, DLC3); - CANCDMOB = (cancdmob | (length << DLC0)); - for(i = 0; i < length; i++) - CANMSG = data[i]; -} - -void can_get_data(int8_t *msg) -{ - uint8_t i; - - for(i = 0; i < 8; i++) - msg[i] = CANMSG; -} - -// Parameter: uint8_t mob: Nummer des Objekts (0-14) -// Funktion setzt den Interrupt für das jeweilige Objekt -void can_set_mob_interrupt(uint8_t mob) -{ - // bugfix von C.H. - // http://www.mikrocontroller.net/topic/98697#1232848 - if (mob < 8) { setbit(CANIE2, iemob[mob]); } - else { setbit(CANIE1, iemob[mob]); } -} - -// Parameter: uint8_t mob: Nummer des Objekts (0-14) -// Funktion löscht den Interrupt für das jeweilige Objekt -void can_clear_mob_interrupt(uint8_t mob) -{ - clearbit(CANIE2, iemob[mob]); -} - -// Rückgabe: uint8_t mob: Nummer des Objekts -// Funktion ermittelt, welches Objekt Interrupt ausgeloest hat -uint8_t can_get_mob_interrupt(void) -{ - uint8_t mob; - uint16_t maske; - maske = CANSIT2 | (CANSIT1 << 8); - - // Wenn alle 32 Bit der Bitmaske 0 sind dann ist ein Fehler aufgetreten - if(maske == 0) - return NOMOB; - - // Die Bitmaske wird so lange nach rechts geschoben, bis Bit0 eine 1 hat. - // Die Anzahl der Schiebeoperatoren gibt somit die Nummer des MOBs zurück - for(mob=0; (maske & 0x01)==0; maske >>= 1, ++mob); - - // Kontrolle: Wenn mob größer als die Anzahl der verfügbaren - // Message Objects ist das Ergebnis falsch - if(mob > 14) - return NOMOB; - - return mob; -} - -void can_disable_mob_usb(uint8_t mob) -{ - answer[0] = CMD_CAN_DISABLE_MOB; - answer[1] = (int8_t)can_disable_mob(mob); - answer[2] = 0; - - CommandAnswer(3); -} - -// Funktion deaktiviert das gewählte Objekt -int can_disable_mob(uint8_t mob) -{ - // Objekt wählen - can_get_mob(mob); - - // Interrupt für dieses Objekt aktivieren - can_clear_mob_interrupt(mob); - - // Betriebsmodus setzen - can_set_mode(CAN_MODE_DISABLED); - - return RSP_OK; -} - - -void can_send_remote_usb(uint8_t mob) -{ - answer[0] = CMD_CAN_SEND_REMOTE; - answer[1] = (int8_t)can_send_remote(mob); - answer[2] = 0; - - CommandAnswer(3); -} - -// Funktion sendet eine Anfrage (Remote Frame) -int can_send_remote(uint8_t mob) -{ - uint8_t mode; - - // Objekt wählen - can_get_mob(mob); - - // Aktuelle Betriebsart sichern - mode = can_get_mode(); - - // Datenübertragung starten - can_set_mode(CAN_MODE_TRANSMIT_REMOTE); - - // Warten bis die Datenübertragung beendet ist (TXOK-Flag von CAN-Controller - // gesetzt) - while (!getbit(CANSTMOB, TXOK)); - - // TXOK-Flag von Hand löschen - clearbit(CANSTMOB, TXOK); - - // Alte Betriebsart wiederherstellen - can_set_mode(mode); - - return RSP_OK; -} - -void can_receive_data_usb(int mob) -{ - uint8_t i; - answer[0] = CMD_CAN_RECEIVE_DATA; - answer[1] = RSP_OK; - - // id - answer[2] = (int8_t) (message.id); - answer[3] = (int8_t) (message.id >> 8); - answer[4] = (int8_t) (message.id >> 16); - answer[5] = (int8_t) (message.id >> 24); - - message.id = 0; - for(i = 0; i < 8; i++) - { - answer[6+i] = message.data[i]; - message.data[i] = 0; - } - answer[14] = 0; - - CommandAnswer(15); -} - -// Interrupt fuer Empfang einer Nachricht -SIGNAL(SIG_CAN_INTERRUPT1) -{ - uint8_t save_canpage; - uint8_t mob; - - // Aktuelle CANPAGE sichern - save_canpage = CANPAGE; - - // Index des MOB ermitteln, der den Interrupt ausgelöst hat - mob = can_get_mob_interrupt(); - - // Falls es kein gültiges MOB war abbrechen - if(mob == NOMOB) - return; - - // Objekt das den Interrupt ausgelöst hat holen - can_get_mob(mob); - - // Id der Nachricht holen - message.id = can_get_id(); - - // Daten des MOBs aus CANMSG auslesen - can_get_data(message.data); - - // Id der Nachricht holen - message.id = can_get_id(); - - // RXOK-Flag löschen - clearbit(CANSTMOB, RXOK); - - // MOB auf Empfang setzen - can_set_mode(CAN_MODE_RECEIVE_DATA); - - // CANPAGE wiederherstellen - CANPAGE = save_canpage; -} - -#endif |