]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/chips/msp430/usci/Msp430UartP.nc
More work on USCI peripheral support.
[tinyos-2.x.git] / tos / chips / msp430 / usci / Msp430UartP.nc
index a987e6d87576d8bda573e0d6f8e9404b7642dcfc..b9f25ede5d067e14023063832864e402f6dec9ca 100644 (file)
@@ -37,31 +37,172 @@ generic module Msp430UartP() {
   provides {
     interface UartStream;
     interface UartByte;
+    interface ResourceConfigure;
   }
   uses {
     interface HplMsp430UsciReg as Registers;
     interface HplMsp430UsciInt as Interrupts;
+    interface HplMsp430GeneralIO as RXD; /* Msp430Gpio no access to PxREN */
+    interface HplMsp430GeneralIO as TXD;
     interface Msp430UsciUartConfigure; /* maybe just Msp430UsciConfigure */
     interface Counter<T32khz,uint16_6>
     interface ArbiterInfo;
   }
 }
 implementation {
-  enum {
-    CLIENT_ID = unique(MSP430_USCIA0_RESOURCE)
-  };
+  #define saveBits(pin, pos, dir, out, ren) { \
+               if (call pin.isOutput()) \
+                       dir |= (1 << pos); \
+               if (call pin.getOut()) \
+                       out |= (1 << pos); \
+               if (call pin.isRen()) \
+                       ren |= (1 << pos); \
+       }
 
-  components Msp430UartP as UartP;
-  UartStream = UartP;
-  UartByte = UartP;
-  Msp430UsciUartConfigure = UartP;
+  #define restoreBits(pin, pos, dir, out, ren) { \
+               if (ren & (1 << pos)) \
+                       call pin.enableRen(); \
+               else \
+                       call pin.disableRen(); \
+               if (out & (1 << pos)) \
+                       call pin.set(); \
+               else \
+                       call pin.clr(); \
+               if (dir & (1 << pos)) \
+                       call pin.makeOutput(); \
+               else \
+                       call pin.makeInput(); \
+       }
 
-  components new Msp430UsciA0C() as UsciC;
-  Resource = UsciC.Resource[CLIENT_ID];
-  ResourceRequested = UsciC.ResourceRequested[CLIENT_ID];
-  ArbiterInfo = UsciC.ArbiterInfo;
-  UartP -> UsciC.Registers;
-  UartP -> UsciC.Interrupts[CLIENT_ID];
-  UartP -> UsciC.ArbiterInfo;
-  UsciC.ResourceConfigure[CLIENT_ID] -> UartP;
+  uint8_t dir; /* Pin state storage to allow for proper unconfiguration */
+  uint8_t out;
+  uint8_t ren;
+  uint8_t* sobuf; /* Original buffer ptr from UartStream.send() */
+  uint8_t solen;       /* Original buffer len from UartStream.send() */
+  uint8_t* sbuf; /* Position of next char to send */
+  uint8_t slen;        /* Len of chars in sbuf to send */
+  bool rxie;   /* Set if rxie has been enabled to UartStream.receive() */
+  uint8_t* robuf; /* Original receive buffer */
+  uint8_t rolen; /* Original (maximum) receive len */
+  uint8_t* rbuf; /* Position of next byte in which to receive a char */
+  uint8_t rlen; /* Remaining length in receive buffer */
+
+  async command void ResourceConfigure.configure();
+  {
+    call Registers.setCtl0(UCSYNC);
+    /* Save pin states */
+    dir = out = ren = 0;
+    saveBits(RXD, 0, dir, out, ren);
+    saveBits(TXD, 1, dir, out, ren);
+    /* FIXME: use Msp430UsciConfig to configure ports */
+    /* FIXME: we may need to have REN/DIR stuff in the configuration... */
+    call RXD.selectModuleFunc();
+    call TXD.selectModuleFunc();
+    /* Clear interrupts; we'll add them as needed */
+    call Registers.clrCtl1(UCRXEIE|UCBRKIE);
+    call Registers.clrIeRx();
+    call Registers.clrIeTx();
+    /* Enable the device */
+    call Registers.clrCtl0(UCSYNC);
+  }
+
+  async command void ResourceConfigure.unconfigure();
+  {
+    /* Disable the device */
+    call Registers.setCtl0(UCSYNC);
+    /* Clear interrupts and interrupt flags */
+    call Registers.clrIeRx();
+    call Registers.clrIeTx();
+    call Registers.clrIfgRx();
+    call Registers.clrIfgTx();
+    /* Restore pins to state just before configure() */
+    restoreBits(RXD, 0, dir, out, ren);
+    restoreBits(TXD, 0, dir, out, ren);
+    call RXD.selectIOFunc();
+    call TXD.selectIOFunc();
+  }
+
+
+  async command error_t UartStream.send( uint8_t* buf, uint16_t len )
+  {
+    if (sobuf || !buf || !len)
+      return FAIL;
+    sobuf = buf;
+    solen = len;
+    call Registers.setIeTx();
+    call Registers.setTxbuf(*sobuf);
+    slen = solen - 1;
+    if (slen)
+      sbuf = sobuf + 1;
+    return SUCCESS;
+  }
+
+  async event void Interrupts.tx()
+  {
+    while (slen && call Registers.getIfgTx()) {
+      call Registers.setTxbuf(*sbuf);
+      if (--slen)
+       sbuf++;
+    }
+    if (slen == 0 && sobuf) {
+      call Registers.clrIeTx();
+      call Registers.clrIfgTx();
+      sobuf = 0;
+      signal UartStream.sendDone(sobuf, solen, SUCCESS);
+    }
+  }
+
+  async command error_t enableReceiveInterrupt()
+  {
+    if (!robuf)
+      call Registers.clrIfgRx();
+    call Registers.setIeRx();
+    rxie = FALSE;
+    return SUCCESS;
+  }
+
+  async command error_t disableReceiveInterrupt()
+  {
+    if (!robuf) {
+      call Registers.clrIeRx();
+      call Registers.clrIfgRx();
+    } else
+      rxie = TRUE;
+    return SUCCESS;
+  }
+
+  async command error_t receive(uint8_t* buf, uint16_t len)
+  {
+    if (robuf || !buf || !len)
+      return FAIL;
+    robuf = rbuf = buf;
+    rolen = rlen = len;
+    if (!call Registers.getIeRx) {
+      call Registers.clrIfgRx();
+      call Registers.setIeRx();
+      rxie = TRUE;
+    } else
+      rxie = FALSE;
+  }
+
+  async event void Interrupts.rx(uint8_t byte)
+  {
+    if (robuf) {
+      /* receive() takes precedence if active */
+      while (rlen && call Registers.getIfgRx()) {
+       *rbuf = byte;
+       if (--rlen)
+         rbuf++;
+      }
+      if (rlen == 0 && robuf) {
+       if (rxie) {
+         call Registers.clrIeRx();
+         call Registers.clrIfgRx();
+       }
+       robuf = 0;
+       signal UartStream.receiveDone(robuf, rolen, SUCCESS);
+      }
+    } else
+      signal UartStream.receivedByte(byte);
+  }
 }