⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 physical.c

📁 adhoc汇聚节点程序源代码(点对多点)——for atmega128
💻 C
字号:
/*
****************************************************************************  
*                        
*              宁波中科集成电路设计中心  版权所有 Copyright 2005
*
*文件名:  Physical.c
*程序员:  
*主要内容:物理层调度控制
*完成日期:2005.5.25
****************************************************************************
*/

#include "physical.h"
#include "message.h"
#include "radiocontrol.h"
#include "os.h"
#include "mac.h"
#include "led.h"

extern uint8_t  OS_BCAST_ADDR;
											// 物理层状态值
enum {
    IDLE,
    RECEIVING,
    TRANSMITTING,
    TRANSMITTING_LAST,
    TRANSMITTING_DONE
};

enum {FREE, BUSY};							// 缓存状态

static char state;							// 物理层状态变量
uint8_t pktLength;							// 包括包头的包长度
OSMACMsg buffer1;							// 用于接收和处理的缓存空间
OSMACMsg buffer2;
char recvBufState;							// 接收缓存状态
char procBufState;							// 处理缓存状态
char* procBufPtr;							// 处理缓存地址,用于接收和处理缓存地址交换
char* sendPtr;								// 指向发送缓存,由上层分配
char* recvPtr;								// 指向接收缓存
char* procPtr;								// 指向处理缓存
static uint8_t txCount;						// 发送字节计数变量
uint8_t recvCount;							// 接收字节计数变量
int16_t crcRx;								// 接收数据包CRC计算结果
int16_t crcTx;								// 发送数据包CRC计算结果

/*************************************************************************
*功能描述:16位CRC计算
*参数说明:待计算的八位数据,上一次计算的CRC结果
*返回值:  CRC计算一次后的结果
**************************************************************************/
int16_t update_crc(char data, int16_t crc)
{
	char i;
	int16_t tmp;
	tmp = (int16_t)(data);
	crc = crc ^ (tmp << 8);
	for (i = 0; i < 8; i++) {
		if (crc & 0x8000)
            crc = (crc << 1) ^ 0x1021;  // << is done before ^
		else
            crc = crc << 1;
	}
	return crc;
}

/*************************************************************************
*功能描述:数据包接收完成任务函数,通知MAC接收处理缓存中的包,并清空处理缓存
*          和接收缓存
*参数说明:无
*返回值:  无
**************************************************************************/
void packet_received(void)
{
	void* tmp;
	char error, intEnabled;
	uint8_t len;
	len = (uint8_t)procPtr[0];
	if (crcRx != *(int16_t*)(procPtr + len - 2)) {
		error = 1;
	} else {
		error = 0;
	}
	tmp = MACPhysicalRxPktDone(procPtr, error);					// 通知MAC对接收到的数据包进行处理
	if (tmp) {
		intEnabled = (* (volatile unsigned char *) (0x3F + 0x20)) & 0x80;
		* (volatile unsigned char *) (0x3F + 0x20) &= ~0x80;		// 关中断
		if (recvBufState == BUSY) {									// 接收缓冲中有数据待处理
            procPtr = recvPtr;										// 处理缓冲获得待处理数据地址
            recvPtr = (char*)tmp;									// 接收缓冲置空闲,可用于接收
            recvBufState = FREE;  
		} else {
            procPtr = 0;											// 接收缓冲中无数据
            procBufPtr = (char *)tmp;
            procBufState = FREE;									// 处理缓冲可用
		}
		if (intEnabled) 
			* (volatile unsigned char *) (0x3F + 0x20) |= 0x80;		// 开中断
		if (procPtr) {												// 处理从接收缓冲得到的数据
            if ( !OSPostTask(packet_received) ) {					// 任务队列满,丢弃数据包
				procBufPtr = procPtr;					
				procBufState = FREE;
				MACPhysicalRxPktDone((void *) 0, 1);				// 通知MAC
            }
		}
	}
}

/*************************************************************************
*功能描述:数据包发送完成任务函数,通知MAC数据包已经发送
*参数说明:无
*返回值:  无
**************************************************************************/
void packet_sent(void)
{
	MACPhysicalTxPktDone(sendPtr);
}

/*************************************************************************
*功能描述:物理层初始化
*参数说明:无
*返回值:  无
**************************************************************************/
result_t PhysicalInit(void)
{
	state = IDLE;
	recvPtr = (char*)&buffer1;
	procBufPtr = (char*)&buffer2;
	recvBufState = FREE;
	procBufState = FREE;
	RadiocontrolInit();
	return SUCCESS;
}

/*************************************************************************
*功能描述:物理层进入空闲状态
*参数说明:无
*返回值:  无
**************************************************************************/
result_t PhysicalIdle(void)
{
	RadiocontrolIdle();
	state = IDLE;
	return SUCCESS;
}

/*************************************************************************
*功能描述:物理层进入睡眠状态
*参数说明:无
*返回值:  无
**************************************************************************/
result_t PhysicalSleep(void)
{
	RadiocontrolSleep();
	state = IDLE;
	return SUCCESS;
}

/*************************************************************************
*功能描述:物理层发送数据包接口函数,进入发送状态,启动整个发送流程
*参数说明:packet:数据包地址 length:物理层要发送的字节数
*返回值:  无
**************************************************************************/
result_t PhysicalTxPkt(void* packet, uint8_t length)
{
	if (length > MAX_PKT_LEN || length < MIN_PKT_LEN) 
		return FAIL;
	if (state != IDLE && state != RECEIVING) 
		return FAIL;

	state = TRANSMITTING;
	RadiocontrolStartTx();					 
	sendPtr = (char*)packet;
	((OSMACMsgPtr)sendPtr)->length = length;  
	pktLength = length;						  
	txCount = 0;

	crcTx=update_crc(sendPtr[0], 0);

	return SUCCESS;
}

/*************************************************************************
*功能描述:发送未完成时,准备下一个要发送的字节,发送完成时进入空闲状态并通知上层
*参数说明:无
*返回值:  无
**************************************************************************/
result_t PhysicalTxByteReady(void)
{																	// 射频控制模块获得数据包下一个字节
	if(state == TRANSMITTING) {
		RadiocontrolTxNextByte(sendPtr[txCount]);
		txCount++;
            if (txCount < pktLength) {								// 不是最后一个字节
				if(txCount < pktLength - 2){						// 是否要计算CRC
					crcTx=update_crc(sendPtr[txCount], crcTx);	
				}
				if(txCount == pktLength - 2){						// 存入CRC结果
					*(int16_t *)(sendPtr + pktLength - 2) = crcTx;
				}
            } else {
				if (txCount == pktLength) {							// 发送最后字节
					state = TRANSMITTING_LAST;
				}
            }
	} else if (state == TRANSMITTING_LAST) {
		state = TRANSMITTING_DONE;
	} else if (state == TRANSMITTING_DONE) {
		RadiocontrolIdle();											// 射频控制转入空闲
		state = IDLE;
		OSPostTask(packet_sent);										// 通知上层发送完成
	}	
	return SUCCESS; 
}

/*************************************************************************
*功能描述:检测到起始符号,通知MAC,准备接收数据,将缓存地址传给MAC
*参数说明:无
*返回值:  无
**************************************************************************/
result_t PhysicalStartSymDetected(void)
{
	// 物理层处于空闲状态时
	if (state == IDLE && recvBufState == FREE) {
		state = RECEIVING;
		recvCount = 0;
		// MAC层可通过此调用对接收缓存中的字段打时间戳
		MACStartSymDetected(recvPtr);
		return SUCCESS;
	}
	return FAIL;
}

/*************************************************************************
*功能描述:将收到的字节打包成数据包,并发出包处理任务
*参数说明:收到的字节
*返回值:  执行结果
**************************************************************************/
result_t PhysicalRxByteDone(char data)
{
	if (state != RECEIVING) 
		return FAIL;

	if (recvCount == 0) {											// 第一个字节为包长度
		if ((uint8_t)data > MAX_PKT_LEN 
            || (uint8_t)data < MIN_PKT_LEN) {						// 包太长或太短,不能正确接收
            RadiocontrolIdle();
            state = IDLE;
			// 通知上层接收包出错
            MACPhysicalRxPktDone((void *) 0, 1);
            return FAIL;
		}
		pktLength = (uint8_t)data;									// 得到包长度
		crcRx = 0;
	}
	recvPtr[recvCount] = data;
	recvCount++;
		
	if (recvCount < pktLength - 1) {
		crcRx=update_crc(data, crcRx);
	} else if (recvCount == pktLength) {							// 接收完成
		if (procBufState == FREE) {									// 处理缓存区可用
            procPtr = recvPtr;										// 数据包存入处理缓存区
            recvPtr = procBufPtr;									// 接收缓存与处理缓存交换地址
            recvBufState = FREE;									// 接收缓存可用
            if (OSPostTask(packet_received) ) {						// 发出接收处理任务
				procBufState = BUSY;
            } else {												// 任务队列满
				procBufPtr = procPtr;								// 丢包
				MACPhysicalRxPktDone((void *) 0, 1);				// 通知MAC已丢包
            }
		} else {													// 处理缓存不可用时不能再接收数据
            recvBufState = BUSY;
		}
		RadiocontrolIdle();											// 转入空闲状态
		state = IDLE;
	}
	return SUCCESS;
}

⌨️ 快捷键说明

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