📄 mac.c
字号:
/*
****************************************************************************
* 宁波中科集成电路设计中心 版权所有 Copyright 2005
* http:\\www.nbicc.com
*文件名: mac.c
*程序员: 夏鹏 xpsonny@nbicc.com
*主要内容:MAC层
*如有问题或BUG,请登录www.wsn.net.cn 提问或用邮件和作者联系
****************************************************************************
*/
/////
#include "led.h"
////
#include "os.h"
#include "mac.h"
#include "message.h"
#include "macClock.h"
#include "global.h"
#include "physical.h"
#include "fun.h"
#include "dataqueue.h"
#include "radiocontrol.h" // 载波监听
#include <avr/io.h>
#include <avr/interrupt.h>
//内部函数声明
static result_t MACTxReset(void); // 清空所有发送任务
static void handleRTS(void* packet);
static void handleCTS(void* packet);
static void* handleDATA(void* packet);
static void handleACK(void* packet);
static void startBcast(void);
//static void sendRTS(void);
//static void sendCTS(void);
//static void sendDATA(void);
static void sendACK(uint8_t DataSrcAddr);
static void startACK(void);
static void tryToSend(void);
static void SetWaitTime(void);
// MAC层状态
enum {
SLEEP,
IDLE,
CARR_SENSE,
TX_PKT,
BACKOFF,
WAIT_CTS,
WAIT_DATA,
WAIT_ACK
};
// 射频状态
enum { RADIO_SLEEP, RADIO_IDLE, RADIO_RX, RADIO_TX };
// 发送方式
enum { BCAST_DATA, SEND_SYNC, SEND_RTS, SEND_CTS, SEND_DATA, SEND_ACK };
//enum { BCAST_DATA,SEND_CTRL};
// MAC 数据包类型
enum { RTS_PKT, CTS_PKT, DATA_PKT, ACK_PKT };
// 状态变量
static char state; // MAC 状态变量
//static char ctrlstate; //MAC层的控制状态,主要用于RTS/CTS 以及ACK的控制
static char oldstate;
static char radioState;
// 发送相关变量
static char txRequest; // 是否接受了一个发送请求,且未发送
static char howToSend; // 发送包方式
static uint8_t txPktLen; // 传输的数据包长度
static uint8_t ctrlPktLen; // 传输的控制包长度
static OSMACMsgPtr dataPkt; // MAC包头指针
static OSMACCtrlMsg ctrlPkt; // 控制包
static OSMACCtrlMsgPtr ctrlPktPt;
static uint8_t AckWaitTime;
/**********************************************************************************
初始化:
等待控制包的时间:timeWaitCtrl
**********************************************************************************/
result_t MACInit()
{
// 初始化状态变量
state = IDLE;
//ctrlstate = IDLE;
oldstate = IDLE;
radioState = RADIO_IDLE;
// 初始化发送相关变量
txRequest = 0;
AckWaitTime = 0;
// 初始化随机数生成器
RandomInit();
// 初始化缓冲队列
QueueInit();
//mac层tick时钟初始化
ClockStart();
// 初始化物理层
PhysicalInit();
return SUCCESS;
}
/*************************************************************************
*功能描述:发送ack开始,开始空闲监听,准备发送ack数据包
*参数说明:
*返回值:
*************************************************************************/
static void tryToSendACK(void){
startACK();
}
/*************************************************************************
*功能描述:发送数据包的开始,开始空闲监听,准备发送广播或者RTS数据包
*参数说明:
*返回值:
**************************************************************************/
static void tryToSend() // 判断是否允许发送,如果是,则进行监听
{
char intEnabled;
if (state == IDLE) { // 空闲时
howToSend = BCAST_DATA;
// 开始载波监听,采用原子操作,防止起始字符检测到调用
intEnabled = inp(SREG) & 0x80;
cli();
if (RadiocontrolCarrierSenseStart(80) == SUCCESS) { // 调用监听函数
state = CARR_SENSE;
}
else {
txRequest =0;
}
if(intEnabled)
sei();
}
else {
txRequest =0; //去锁
}
return;
}
/*************************************************************************
*功能描述:发送广播数据包的接口函数
*参数说明:包地址,包长度(MAC包数据部分的长度)
*返回值:
**************************************************************************/
result_t MACBroadcastMsg(void* data, uint8_t length)
{
char intEnabled;
// 错误的发送方式
if (data == 0 || length == 0 || length > MAX_PKT_LEN - MAC_HEADER_LEN) {
return FAIL;
}
// 设置发送请求标识
intEnabled = inp(SREG) & 0x80;
cli();
if ((txRequest == 0)&&(AckWaitTime == 0)) {
txRequest = 1;
if (intEnabled) sei();
} else {
if (intEnabled) sei();
return FAIL;
}
dataPkt = (OSMACMsgPtr)data;
txPktLen = length + MAC_HEADER_LEN;
// 数据包包头设置
dataPkt->type = DATA_PKT;
dataPkt->toAddr = OS_BCAST_ADDR;
dataPkt->fromAddr = OS_LOCAL_ADDRESS;
dataPkt->group = 0x01;
tryToSend();
return SUCCESS;
}
/*************************************************************************
*功能描述:发送单播数据包的接口函数
*参数说明:包地址,包长度(包括包头),目的地址
*返回值:
**************************************************************************/
result_t MACUnicastMsg(void* data, uint8_t length, uint8_t toAddr)
{
char intEnabled;
// 错误的发送方式
if (data == 0 || length == 0 || length > MAX_PKT_LEN - MAC_HEADER_LEN) {
return FAIL;
}
// 设置发送请求标识
intEnabled = inp(SREG) & 0x80;
cli();
if ((txRequest == 0)&&(AckWaitTime == 0)) {
txRequest = 1;
if (intEnabled) sei();
} else {
if (intEnabled) sei();
return FAIL;
}
dataPkt = (OSMACMsgPtr)data;
txPktLen = length + MAC_HEADER_LEN;
// 数据包包头设置
dataPkt->type = DATA_PKT;
dataPkt->toAddr = toAddr;
dataPkt->fromAddr = OS_LOCAL_ADDRESS;
dataPkt->group = 0x01;
tryToSend();
return SUCCESS;
}
/*************************************************************************
*功能描述:发送ack任务
*参数说明:无
*返回值:
**************************************************************************/
static void sendACK(uint8_t DataSrcAddr){
// 控制包初始化
ctrlPkt.fromAddr = OS_LOCAL_ADDRESS;
ctrlPkt.type = ACK_PKT;
ctrlPkt.group = 0x01;
ctrlPkt.ack = 0x06;
ctrlPkt.length = 1;
ctrlPktPt = &ctrlPkt;
ctrlPktPt->toAddr = DataSrcAddr;
ctrlPktLen = 1 + MAC_HEADER_LEN;
tryToSendACK();
}
/*************************************************************************
*功能描述:强行取消所有正在发送的任务
*参数说明:无
*返回值:
**************************************************************************/
static result_t MACTxReset()
{
radioState = RADIO_IDLE;
txRequest = 0;
state = IDLE;
oldstate = IDLE;
return SUCCESS;
}
/*************************************************************************
*功能描述:发送广播包
*参数说明:无
*返回值:
**************************************************************************/
static void startBcast()
{
PhysicalTxPkt(dataPkt, txPktLen); // 调用物理层发送接口发送数据包
radioState = RADIO_TX;
state = TX_PKT;
}
/*************************************************************************
*功能描述:发送ack帧
*参数说明:
*返回值:
**************************************************************************/
static void startACK()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -