#include "main.h"
#include "ad0x0_spi.h"
#include "../admisc/ad0x0_timman.h"
#include "stm32f1xx_hal_spi.h"
#include "ad0x0_spi_ext.h"
#include <string.h>


static uint8_t	ext_ub[AD0X0_SPI_EXT_COUNT],ext_l[AD0X0_SPI_EXT_COUNT];
static ad0x0_spi_ext_t ext_funcs[AD0X0_SPI_EXT_COUNT];
//когда в еtypedef структуры чтото изменится - я 100% это прое..."упущу"
static ad0x0_memman_desc_t ext_mm={ext_ub,ext_l,0,AD0X0_SPI_EXT_COUNT};
static volatile uint8_t ad0x0_ext_lock=0;

void ext_err(void){
	__ASM("nop");
}

void	ad0x0_spi_ext_init(void	(*perr)(void)){
	//uint8_t	*puba,*pla,cur_ei,total_count;
	/*_p_spi_desc->ext_mm.puba=ext_ub;
	_p_spi_desc->ext_mm.pla=ext_l;
	_p_spi_desc->ext_mm.total_count=AD0X0_SPI_EXT_COUNT;	*/
	ext_mm.perr=perr;
	ad0x0_memman_init(&ext_mm);
	/*ad0x0_spi1_desc.ext_mm.puba=ad0x0_spi1_desc.ext_ub;
	ad0x0_spi1_desc.ext_mm.pla=ad0x0_spi1_desc.ext_l;
	ad0x0_spi1_desc.ext_mm.total_count=AD0X0_SPI_EXT_COUNT;
	ad0x0_memman_init(&ad0x0_spi1_desc.ext_mm);*/
}

ad0x0_spi_ext_t *ad0x0_spi_ext_get_pdesc(uint8_t _handle){
	return &ext_funcs[_handle];
}

/*void	ad0x0_spi_ext_process_old(ad0x0_spi_desc_s *pdspi,uint8_t _handle){
	if(_handle & 0x80){
		pdspi->perrfunc();//УБРАТЬ ПОТОМ
		}
//	ext_funcs[_handle].calls_count++;
	ad0x0_spi_ext_t ef=ext_funcs[_handle];	
	//memset(ext_funcs+_handle,0,sizeof(ad0x0_spi_ext_t));
//	ext_funcs[_handle].calls_count=0;
	//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
	ad0x0_memman_free(&ext_mm,_handle);	
	///^^^^^^^^^^^^^^^^
	//if(ef.spi!=pdspi->spix || ef.calls_count>1){		pdspi->perrfunc();//УБРАТЬ ПОТОМ	}
	if(pdspi->spix==((SPI_TypeDef *)SPI2_BASE) && ef.pbuf_rx==0 && ef.pSetTXRXBuf!=0)
	{
		pdspi->perrfunc();
	}
	if(ef.pSetTXRXBuf){
		ef.pSetTXRXBuf(pdspi,&ef);		
	}
	if(ef._p_cb_func){
		ef._p_cb_func(ef.sf_id, pdspi);
	}
}*/

void	ad0x0_spi_ext_pre_process(ad0x0_spi_desc_s *pdspi,uint8_t _handle){
	/*хрень в том, что вызов колбэков порождает рекурсивное выделение новых блоков
	по этому мы идем на жертвы и делаем как ниже, чтобы быстрее освободить
	ячейку, с другой стороны мы используем стэк... ПЕРЕДЕЛАТЬ*/
	if(_handle & 0x80){
		pdspi->perrfunc();//УБРАТЬ ПОТОМ
		}
//	ext_funcs[_handle].calls_count++;
	ad0x0_spi_ext_t *pef=ext_funcs+_handle;	
	//if(pdspi->spix==((SPI_TypeDef *)SPI2_BASE) && pef->pbuf_rx==0 && pef->pSetTXRXBuf!=0)	{		pdspi->perrfunc();	}
	if(pef->p_pre_SetTXRXBuf){
		pef->p_pre_SetTXRXBuf(pdspi,pef);
	}
	if(pef->_p_pre_cb_func){
		pef->_p_pre_cb_func(pef->sf_id, pdspi, (void*)pef);
	}
	//ad0x0_memman_free(&ext_mm,_handle);		 это в ad0x0_spi_ext_post_process
}

void	ad0x0_spi_ext_post_process(ad0x0_spi_desc_s *pdspi,uint8_t _handle){
	/*хрень в том, что вызов колбэков порождает рекурсивное выделение новых блоков
	по этому мы идем на жертвы и делаем как ниже, чтобы быстрее освободить
	ячейку, с другой стороны мы используем стэк... ПЕРЕДЕЛАТЬ*/
	if(_handle & 0x80){
		pdspi->perrfunc();//УБРАТЬ ПОТОМ
		}
//	ext_funcs[_handle].calls_count++;
	ad0x0_spi_ext_t *pef=ext_funcs+_handle;	
	//if(pdspi->spix==((SPI_TypeDef *)SPI2_BASE) && pef->pbuf_rx==0 && pef->pSetTXRXBuf!=0)	{		pdspi->perrfunc();	}

	if(pef->_p_post_cb_func){
		pef->_p_post_cb_func(pef->sf_id, pdspi, (void*)pef);
	}
	//ото тут как бы повнимательнее: если ссылок ноль, то выкидываем, иначе уменьшаем рекфкаунт
	if(!pef->reference_count){
		ad0x0_memman_free(&ext_mm,_handle);
	}else pef->reference_count--;
}

uint8_t ad0x0_spi_ext_get(uint8_t *_p_out_handle,ad0x0_spi_ext_t **_p_out_desc){
	int was_masked=__disable_irq();	
	if(ad0x0_ext_lock){
		if(!was_masked)__enable_irq();	
		return 0;
	}
	ad0x0_ext_lock=1;
	if(!ad0x0_memman_get(&ext_mm,_p_out_handle)){
		ad0x0_ext_lock=0;//!!!!!!!!!!!!!!!добавил 29.01.2021... ну я и баран.......
		if(!was_masked)__enable_irq();
		return 0;
	}
	*_p_out_desc=ext_funcs + *_p_out_handle;
	memset(*_p_out_desc,0,sizeof(ad0x0_spi_ext_t));
	//(*_p_out_desc)->reference_count=1;
	/*если две строки переставить местами, то после включения прерываний, 
	пока не выполнился лок=0, вызовется прерывание и все нахер повиснет 
	в обработчике DMA ad0x0 16.10.2020 ПЕРЕПРОВЕРИТЬ ВСЕ УЧАСтки подобные*/
	ad0x0_ext_lock=0;
	if(!was_masked)__enable_irq();	
	return 1;
}

void	EXT_SetTXRXBuf(ad0x0_spi_desc_s *pdspi,void *_p_ad0x0_spi_ext_t){
	ad0x0_spi_ext_t *p=_p_ad0x0_spi_ext_t;
	pdspi->tx_pbuf=p->pbuf_tx;
	pdspi->rx_pbuf=p->pbuf_rx;
	pdspi->pbuf_counter=p->pbuf_count;
}

void	ad0x0_spi_ext_clear(ad0x0_spi_ext_t *pf){
	memset(pf,0,sizeof(ad0x0_spi_ext_t));
	//pf->pSetTXRXBuf=SetTXRXBuf;
}
