#include "buff.h"
#include "stdlib.h"
#include "string.h"
#include "stdio.h"



#ifdef RT_THREAD
  #include "rthw.h"
  #define IRQ_DISABLE() rt_base_t irq_stat=rt_hw_interrupt_disable( )
  #define IRQ_ENABLE()	rt_hw_interrupt_enable (irq_stat)
  #define MUTEX_INIT(buff,name)  buff->mutex=rt_mutex_create(name,RT_IPC_FLAG_FIFO)
  #define MUTEX_TAKE(buff)  rt_mutex_take(buff->mutex,RT_WAITING_FOREVER)
  #define MUTEX_RELEASE(buff) rt_mutex_release(buff->mutex);
#else
	#define IRQ_DISABLE() { }
	#define IRQ_ENABLE()	{ }
  #define MUTEX_INIT(buff,name) {}
  #define MUTEX_TAKE(buff)  {}
  #define MUTEX_RELEASE(buff) {}
#endif


  
static int g_buff_num=0;  
  

int buff_init(data_buff *buff,int size,int use_frame,int frame_start,int frame_end)
{ 
  int buff_index;
  char str[20];
  if(buff==0) return -1;
  if(buff->buff==0)
  {
    IRQ_DISABLE();
    buff_index=g_buff_num;
    g_buff_num++;
    IRQ_ENABLE();
    buff->buff=malloc(size);
    if(buff->buff==0) return -1;
    memset(buff->buff,0,sizeof(size));
    buff->buff_len= size;
    buff->use_frame=use_frame;
    buff->frame_start=frame_start;
    buff->frame_end=frame_end;
    sprintf(str,"buff_#%d",buff_index);
    MUTEX_INIT(buff,str);
  }
  buff_clear(buff);
  return 0;
}


int buff_deinit(data_buff *buff)
{
  if(buff==0) return -1;
  if(buff->buff)
  {
    free(buff->buff);
    buff->buff=0;
    buff->buff_len=0;
  }
  return 0;
}


int buff_get_used(data_buff *buff)
{
  int ret=-1;
  IRQ_DISABLE();
  ret=buff->buff_used;
  IRQ_ENABLE();
  return ret;
}




int buff_save_byte(data_buff *buff,uint8_t data)
{
  if(buff==0) return -1;
	int ret=-1;
	IRQ_DISABLE();
	if((!buff->use_frame)||(data==buff->frame_start)) buff->active=1;
	if((buff->buff_used<buff->buff_len)&&buff->active)
	{
		buff->buff[buff->save_ptr]=data;
		buff->buff_used++;
		if((buff->use_frame)&&(data==buff->frame_end)) {
			buff->frame_num++;
			buff->active=0;
		}
		buff->save_ptr++;
		if (buff->save_ptr>=buff->buff_len)
			buff->save_ptr=0;
		ret= 0;
	}
	IRQ_ENABLE();
	return ret;
}


int buff_save_bytes(data_buff *buff,const uint8_t *data,int len)
{
  if(buff==0) return -1;
  int ret=-1;
  MUTEX_TAKE(buff);
  if (buff->buff_used+len<=buff->buff_len)
  {
    while(len--)
    {
      ret=buff_save_byte(buff,*data);data++;
      if(ret!=0) break;
    }
  }
  MUTEX_RELEASE(buff);
  return ret;
}



int buff_read_byte(data_buff *buff,uint8_t *data)
{
  if(buff==0) return -1;
	int ret=-1;
	IRQ_DISABLE();
	if (((buff->frame_num)&&(buff->buff_used))||((!buff->use_frame)&&(buff->buff_used)))
	{
		*data=buff->buff[buff->read_ptr];
		buff->buff_used--;
		if((buff->use_frame)&&(*data==buff->frame_end)) buff->frame_num--;
		buff->read_ptr++;
		if (buff->read_ptr>=buff->buff_len)
			buff->read_ptr=0;
		ret= 0;
	}
	IRQ_ENABLE();
	return ret;
}



int buff_read_bytes(data_buff *buff,uint8_t *data,int len)
{
  if(buff==0) return -1;
  int ret=-1;
  MUTEX_TAKE(buff);
  if (buff->buff_used>=len)
  {
    while(len--)
    {
      ret=buff_read_byte(buff,data);data++;
      if(ret!=0) break;
    }
  }
  MUTEX_RELEASE(buff);
  return ret;
}




int buff_clear(data_buff *buff)
{
  if(buff==0) return -1;
	IRQ_DISABLE();
	buff->buff_used=0;
	buff->read_ptr=0;
	buff->save_ptr=0;
	buff->frame_num=0;
	buff->active=0;
	IRQ_ENABLE();
	return 0;
}






