From df8c4a5ae6c8d7933dc17ca192f1697b646a13fb Mon Sep 17 00:00:00 2001
From: Oleg Hahm <oleg@hobbykeller.org>
Date: Thu, 22 Aug 2013 23:34:10 +0200
Subject: [PATCH] added board dependent part of the cc2420 for TelosB

---
 telosb/driver_cc2420.c | 247 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 247 insertions(+)
 create mode 100644 telosb/driver_cc2420.c

diff --git a/telosb/driver_cc2420.c b/telosb/driver_cc2420.c
new file mode 100644
index 0000000000..67d926855f
--- /dev/null
+++ b/telosb/driver_cc2420.c
@@ -0,0 +1,247 @@
+  /*
+   * driver_cc2420.c - Implementation of the board dependent cc2420 functions.
+   * Copyright (C) 2005, 2006, 2007, 2008 by Thomas Hillebrandt and Heiko Will
+   * Copyright (C) 2013 Oliver Hahm <oliver.hahm@inria.fr>
+   *
+   * This source code is licensed under the GNU Lesser General Public License,
+   * Version 2.  See the file LICENSE for more details.
+   */
+
+#include <stdio.h>
+
+#include <board.h>
+#include <cpu.h>
+#include <irq.h>
+#include <hwtimer.h>
+
+#include <cc2420.h>
+
+#define ENABLE_DEBUG    (1)
+#include "debug.h"
+
+#define CC2420_RESETn_PIN   0x40
+#define CC2420_VREGEN_PIN   0x20
+
+#define CC2420_FIFOP_PIN    0x01
+#define CC2420_GIO0_PIN     0x08
+#define CC2420_GIO1_PIN     0x10
+#define CC2420_CCA_PIN      0x40
+#define CC2420_SFD_PIN      0x02
+
+#define CC2420_FIFOP        (P1IN & CC2420_FIFOP_PIN)   /* FIFOP <-> packet interrupt (P1.0) */
+#define CC2420_GIO0         (P1IN & CC2420_GIO0_PIN)    /* FIFO  <-> GIO0 - RX data available (P1.3) */
+#define CC2420_GIO1         (P1IN & CC2420_GIO1_PIN)    /* CCA   <-> GIO1 - clear channel (P1.4) */
+#define CC2420_SFD          (P4IN & CC2420_SFD_PIN)     /* SFD   <-> TBL - start frame delimiter (P4.1) */
+
+#define CC2420_CS_LOW       (P4OUT &= ~0x04)            /* P4.2 */
+#define CC2420_CS_HIGH      (P4OUT |= 0x04)
+
+volatile int abort_count;
+volatile int retry_count = 0;
+
+void cc2420_reset(void)
+{
+    P4OUT |= CC2420_VREGEN_PIN;
+    P4OUT &= ~CC2420_RESETn_PIN;
+    hwtimer_wait(500);
+    P4OUT |= CC2420_RESETn_PIN;
+}
+
+void cc2420_gio0_enable(void)
+{
+    P1IFG &= ~CC2420_GIO0_PIN;     /* Clear IFG for GIO0 */
+    P1IE |= CC2420_GIO0_PIN;       /* Enable interrupt for GIO0 */
+}
+
+void cc2420_gio0_disable(void)
+{
+    P1IE &= ~CC2420_GIO0_PIN;      /* Disable interrupt for GIO0 */
+    P1IFG &= ~CC2420_GIO0_PIN;     /* Clear IFG for GIO0 */
+}
+
+void cc2420_gio1_enable(void)
+{
+    P1IFG &= ~CC2420_GIO1_PIN;     /* Clear IFG for GIO1 */
+    P1IE |= CC2420_GIO1_PIN;       /* Enable interrupt for GIO1 */
+}
+
+void cc2420_gio1_disable(void)
+{
+    P1IE &= ~CC2420_GIO1_PIN;      /* Disable interrupt for GIO1 */
+    P1IFG &= ~CC2420_GIO1_PIN;     /* Clear IFG for GIO1 */
+}
+
+void cc2420_before_send(void)
+{
+    /* Disable SFD interrupt before sending packet */
+    /* However this is not used atm */
+}
+
+void cc2420_after_send(void)
+{
+    /* Enable SFD interrupt after sending packet */
+    /* However this is not used atm */
+}
+
+
+int cc2420_get_gio0(void)
+{
+    return  CC2420_GIO0;
+}
+
+int cc2420_get_gio1(void)
+{
+    return  CC2420_GIO1;
+}
+
+int cc2420_get_sfd(void)
+{
+    return CC2420_SFD;
+}
+
+void cc2420_spi_cs(void)
+{
+    CC2420_CS_LOW;
+}
+
+uint8_t cc2420_txrx(uint8_t data)
+{
+    /* Ensure TX Buf is empty */
+    long c = 0;
+    IFG1 &= ~UTXIFG0;
+    IFG1 &= ~URXIFG0;
+    U0TXBUF = data;
+    while(!(IFG1 & UTXIFG0)) {
+        if (c++ == 1000000) {
+            puts("cc2420_txrx alarm()");
+        }
+    }
+    /* Wait for Byte received */
+    c = 0;
+    while(!(IFG1 & URXIFG0)) {
+        if (c++ == 1000000) {
+            puts("cc2420_txrx alarm()");
+        }
+    }
+    return U0RXBUF;
+}
+
+
+void cc2420_spi_select(void)
+{
+    CC2420_CS_LOW;
+}
+
+void cc2420_spi_unselect(void) {
+    CC2420_CS_HIGH;
+}
+
+void cc2420_init_interrupts(void)
+{
+    unsigned int state = disableIRQ();  /* Disable all interrupts */
+    P1SEL &= ~CC2420_FIFOP_PIN;         /* must be <> 1 to use interrupts */
+
+    P1IE &= ~CC2420_FIFOP_PIN;      /* Disable interrupt for GIO0 */
+    P1IFG &= ~CC2420_FIFOP_PIN;     /* Clear IFG for GIO0 */
+    restoreIRQ(state);              /* Enable all interrupts */
+}
+
+void cc2420_spi_init(void)
+{
+    /* Switch off async UART */
+    while(!(U0TCTL & TXEPT));   /* Wait for empty UxTXBUF register */
+    IE1 &= ~(URXIE0 + UTXIE0);  /* Disable USART0 receive&transmit interrupt */
+    ME1 &= ~(UTXE0 + URXE0);
+
+    /* configure SPI-related pins */
+    P3SEL     |=  0x0E;                           /* P3.1 -  SIMO mode, P3.2 - SOMI mode, P3.3 - SCL mode */
+    P3DIR     |=  0x0A;                           /* P3.1 and P3.3 as output */
+    P3DIR     &= ~(0x04);                         /* P3.2 as input for SOMI */
+    P4OUT     |=  0x04;                           /* P4.2 radio CS, hold high */
+    P4DIR     |=  0x04;                           /* P4.2 radio CS, output */
+ 
+    /* Keep peripheral in reset state */
+    U0CTL  = SWRST;
+
+    /* 8-bit SPI Master 3-pin mode, with SMCLK as clock source */
+    /* CKPL works also, but not CKPH+CKPL or none of them!! */
+    U0CTL |= CHAR + SYNC + MM;
+    U0TCTL = CKPH + SSEL1 + SSEL0 + STC + TXEPT;;
+    
+    /* Ignore clockrate argument for now, just use clock source/2 */
+    /* SMCLK = 8 MHz */
+    U0BR0 = 0x02;  /* Ensure baud rate >= 2 */
+    U0BR1 = 0x00;
+    U0MCTL = 0x00; /* No modulation */
+    U0RCTL = 0x00; /* Reset Receive Control Register */
+   
+    /* Enable SPI mode */
+    ME1 |= USPIE0;
+
+    /* Release for operation */
+    U0CTL  &= ~SWRST;
+}
+
+/*
+ * CC1100 receive interrupt
+ */
+interrupt (PORT1_VECTOR) __attribute__ ((naked)) cc2420_isr(void){
+    __enter_isr();
+     /* Check IFG */
+    if ((P1IFG & CC2420_FIFOP_PIN) != 0) {
+        P1IFG &= ~CC2420_FIFOP_PIN;
+        if (cc2420_get_gio0()) {
+            cc2420_rx_irq();
+            DEBUG("rx interrupt");
+        }
+        else {
+            cc2420_rxoverflow_irq();
+            DEBUG("[CC2420] rxfifo overflow");
+        }
+    }
+
+    else {
+        puts("cc2420_isr(): unexpected IFG!");
+        /* Should not occur - only GDO1 and GIO1 interrupts are enabled */
+    }
+    __exit_isr();
+}
+    
+/**
+\brief TimerB CCR1-6 interrupt service routine (taken from OpenWSN)
+*/
+interrupt (TIMERB0_VECTOR) __attribute__ ((naked)) radiotimer_isr(void) {
+   uint16_t tbiv_local;
+   
+   /* reading TBIV returns the value of the highest pending interrupt flag */
+   /* and automatically resets that flag. We therefore copy its value to the */
+   /* tbiv_local local variable exactly once. If there is more than one  */
+   /* interrupt pending, we will reenter this function after having just left */
+   /* it. */
+   tbiv_local = TBIV;
+   
+   switch (tbiv_local) {
+      case 0x0002: /* CCR1 fires */
+        if (TBCCTL1 & CCI) {
+            /* SFD pin is high */
+            DEBUG("start of a frame\n");
+        }
+        else {
+            /* SFD pin is low */
+            DEBUG("end of a frame\n");
+         }
+         break;
+      case 0x0004: /* CCR2 fires */
+         break;
+      case 0x0006: /* CCR3 fires */
+         break;
+      case 0x0008: /* CCR4 fires */
+         break;
+      case 0x000a: /* CCR5 fires */
+         break;
+      case 0x000c: /* CCR6 fires */
+         break;
+      case 0x000e: /* timer overflow */
+         break;
+   }
+}
-- 
GitLab