atm128i2cmasterpacketp.nc

来自「tinyos-2.0源代码!转载而已!要的尽管拿!」· NC 代码 · 共 345 行

NC
345
字号
/* * Copyright (c) 2006 Stanford University. * All rights reserved. * * 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 Stanford University 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 STANFORD * UNIVERSITY OR ITS 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. */#include "Atm128I2C.h"/** * This driver implements an interupt driven I2C Master controller  * Hardware Abstraction Layer (HAL) to the ATmega128  * two-wire-interface (TWI) hardware subsystem. * * @author Philip Levis * * @version $Id: Atm128I2CMasterPacketP.nc,v 1.1.2.1 2006/06/08 03:22:03 scipio Exp $ */generic module Atm128I2CMasterPacketP() {  provides interface AsyncStdControl;  provides interface I2CPacket<TI2CBasicAddr>;  provides interface Atm128I2C;    uses interface HplAtm128I2CBus as I2C;  uses interface Leds as ReadDebugLeds;  uses interface Leds as WriteDebugLeds;}implementation {  enum {    I2C_OFF          = 0,    I2C_IDLE         = 1,    I2C_BUSY         = 2,          I2C_ADDR         = 3,    I2C_DATA         = 4,    I2C_STARTING     = 5,    I2C_STOPPING     = 6,  } atm128_i2c_state_t;  uint8_t state = I2C_OFF;  i2c_flags_t packetFlags;   uint8_t* packetPtr;  uint8_t packetLen;  uint8_t index;  uint16_t packetAddr;  bool reading = FALSE;  void i2c_abort(error_t err) {    atomic {      // Cycle the I2C      call I2C.readCurrent();      call I2C.enableInterrupt(FALSE);      call I2C.enable(FALSE);      call I2C.sendCommand();      call I2C.readCurrent();      call I2C.enable(TRUE);      call I2C.sendCommand();      state = I2C_IDLE;      if (reading) {	signal I2CPacket.readDone(err, packetAddr, packetLen, packetPtr);      }      else {	signal I2CPacket.writeDone(err, packetAddr, packetLen, packetPtr);      }    }  }    async command error_t AsyncStdControl.start() {    atomic {      if (state == I2C_OFF) {	call I2C.init(FALSE);	call I2C.readCurrent();	call I2C.enable(TRUE);	call I2C.enableInterrupt(FALSE);	call I2C.sendCommand();	state = I2C_IDLE;	return SUCCESS;      }      else {	return FAIL;      }    }  }  async command error_t AsyncStdControl.stop() {    atomic {      if (state == I2C_IDLE) {	call I2C.readCurrent();	call I2C.enable(FALSE);	call I2C.enableInterrupt(FALSE);	call I2C.setInterruptPending(FALSE);	call I2C.off();	state = I2C_OFF;	return SUCCESS;      }      else {	return FAIL;      }    }  }  async command error_t I2CPacket.read(i2c_flags_t flags, uint16_t addr, uint8_t len, uint8_t* data) {    atomic {      if (state == I2C_IDLE) {	state = I2C_BUSY;      }      else if (state == I2C_OFF) {	return EOFF;      }      else {	return EBUSY;      }    }    /* This follows the procedure described on page 209 of the atmega128L     * data sheet. It is synchronous (does not handle interrupts).*/    atomic {      packetAddr = addr;      packetPtr = data;      packetLen = len;      packetFlags = flags;      index = 0;      reading = TRUE;    }    /* Clear interrupt pending, send the I2C start command and abort       if we're not in the start state.*/    call I2C.readCurrent();    atomic {      call I2C.enableInterrupt(TRUE);      call I2C.setInterruptPending(TRUE);      call I2C.enableAck(FALSE);            if (flags & I2C_START) {        call I2C.setStart(TRUE);        state = I2C_STARTING;      }      else if (len > 1 || (len > 0 && flags & I2C_ACK_END)) {        call I2C.enableAck(TRUE);        state = I2C_DATA;      }      else if (len == 1) { // length is 1        state = I2C_DATA;      }      else if (flags & I2C_STOP) {        state = I2C_STOPPING;        call I2C.enableAck(FALSE);        call I2C.setStop(TRUE);      }      call I2C.sendCommand();    }    return SUCCESS;  }  async command error_t I2CPacket.write(i2c_flags_t flags, uint16_t addr, uint8_t len, uint8_t* data) {    atomic {      if (state == I2C_IDLE) {	state = I2C_BUSY;      }      else if (state == I2C_OFF) {	return EOFF;      }      else {	return EBUSY;      }    }    /* This follows the procedure described on page 209 of the atmega128L     * data sheet. It is synchronous (does not handle interrupts).*/    atomic {      packetAddr = addr;      packetPtr = data;      packetLen = len;      packetFlags = flags;      index = 0;      reading = FALSE;    }    call I2C.readCurrent();    atomic {      call I2C.setInterruptPending(TRUE);      call I2C.enableAck(TRUE);      call I2C.enableInterrupt(TRUE);            if (flags & I2C_START) {        call I2C.setStart(TRUE);	//	call WriteDebugLeds.led0On();        state = I2C_STARTING;      }      else if (len > 0) {        state = I2C_DATA;	call I2C.write(data[index]);      }      else if (flags & I2C_STOP) {        state = I2C_STOPPING;        call I2C.enableAck(FALSE);        call I2C.setStop(TRUE);      }      else { // A 0-length packet with no start and no stop....	state = I2C_IDLE;	return FAIL;      }      call I2C.sendCommand();    }    return SUCCESS;  }    /**   * A command has been sent over the I2C.   * The diversity of I2C options and modes means that there are a   * plethora of cases to consider. To simplify reading the code,   * they're described here and the corresponding statements   * are only labelled with identifying comments.   *   * When reading:   *  R1) A start condition has been requested. This requires    *      sending the start signal. When the interrupt comes in,   *      send the first byte of the packet. This driver   *      detects this condition by the START flag being set.    *      A successful send of the start clears the local copy of   *      the flag. The driver does not distinguish between start   *      and repeated start.   *  R2) Sending the address byte with the read bit set.   *  R3) Sending the first byte of a two-byte address with the   *      read bit set.    *  R4) Sending the second byte of a two-byte address.   *  R5) Reading any byte except the last byte of a packet.   *  R6) Reading the last byte of the packet, with ACK_END requested.   *  R7) Reading the last byte of the packet, with ACK_END cleared.   *  R8) Sending a stop condition.   */  async event void I2C.commandComplete() {    call I2C.readCurrent();    atomic {      if (state == I2C_DATA) {	if (reading == TRUE) {	  if (index < packetLen) {	    packetPtr[index] = call I2C.read();	    if (index == packetLen - 1 &&                !(packetFlags & I2C_ACK_END)) {               call I2C.enableAck(FALSE);            }          }	  else {	    call I2C.enableInterrupt(FALSE);	    if (packetFlags & I2C_STOP) {	      packetFlags &= ~I2C_STOP;	      call I2C.setStop(TRUE);	      call I2C.status();	    }	    else {	      call I2C.setInterruptPending(FALSE);	    }	    call I2C.sendCommand();	    state = I2C_IDLE;	    signal I2CPacket.readDone(SUCCESS, packetAddr, packetLen, packetPtr);	    return;	  }	  index++;	  call I2C.sendCommand();	  return;        }        else { // Writing	  if (index < packetLen) {	    call I2C.write(packetPtr[index]);	    index++;	    call I2C.sendCommand();	  }	  else {	    call I2C.enableInterrupt(FALSE);	    if (packetFlags & I2C_STOP) {	      packetFlags &= ~I2C_STOP;	      call I2C.setStop(TRUE);	      call WriteDebugLeds.led1On();	    }	    else {	      call I2C.setInterruptPending(FALSE);	    }	    call I2C.sendCommand();	    state = I2C_IDLE;	    call WriteDebugLeds.led2On();	    signal I2CPacket.writeDone(SUCCESS, packetAddr, packetLen, packetPtr);	    return;	  }	}      }      else if (state == I2C_STARTING) {	packetFlags &= ~I2C_START;	call I2C.setStart(FALSE);	if (call I2C.status() != ATM128_I2C_START &&	    call I2C.status() != ATM128_I2C_RSTART) {	  if (reading) {	    //call ReadDebugLeds.set(call I2C.status() >> 4);	  }	  //call ReadDebugLeds.led2On();	  i2c_abort(FAIL);	  return;	}	state = I2C_ADDR;	call I2C.enableAck(TRUE);      }      if (state == I2C_ADDR) {	if (reading == TRUE) {	  call I2C.write((packetAddr & 0xff) | ATM128_I2C_SLA_READ);	}	else	  call I2C.write((packetAddr & 0xff) | ATM128_I2C_SLA_WRITE);	state = I2C_DATA;	call I2C.sendCommand();      }    }  }  async command void Atm128I2C.stop() {    atomic {      call I2C.readCurrent();      call I2C.enableInterrupt(FALSE);      call I2C.setStop(TRUE);      call I2C.setInterruptPending(TRUE);      call I2C.sendCommand();    }  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?