Программный модуль для очистителя воздуха RAC-3706S. v.1.5



ПО является неотъемлемой частью очистителя воздуха RAC-3706S, отдельно потребителю не поставляется и эксплуатируется только в составе устройства.

Фрагмент исходного кода
////////////////////////////////////////////////////////////////

//RAC-3706S

//v1.5

//application.c

////////////////////////////////////////////////////////////////

#include "common.h"
#include "application.h"
#include "api.h"

#include "adc.h"
#include "clk.h"
#include "buz.h"
#include "keyb.h"
#include "display.h"

#include "nrf_soc.h"	

#include "rtc1.h"	//(ash)

////////////////////////////////////////////////////////////////

void RTC1_COMPARE3_Handler(void);	//(ash)

////////////////////////////////////////////////////////////////

u16 TRC_VAR_TAB[]= {
325,  // 0
320,  // 1
315,  // 2
310,  // 3
305,  // 4
300,  // 5
295,  // 6
290,  // 7
285,  // 8
280,  // 9
275,  // 10
272,  // 11
269,  // 12
266,  // 13
263,  // 14
260,  // 15
257,  // 16
254,  // 17
251,  // 18
248,  // 19
245,  // 20
243,  // 21
241,  // 22
239,  // 23
237,  // 24
235,  // 25
233,  // 26
231,  // 27
229,  // 28
227,  // 29
225,  // 30
223,  // 31
221,  // 32
219,  // 33
217,  // 34
215,  // 35
213,  // 36
211,  // 37
209,  // 38
207,  // 39
205,  // 40
203,  // 41
201,  // 42
199,  // 43
197,  // 44
195,  // 45
193,  // 46
191,  // 47
189,  // 48
187,  // 49
185,  // 50
184,  // 51
183,  // 52
182,  // 53
181,  // 54
180,  // 55
179,  // 56
178,  // 57
177,  // 58
176,  // 59
175,  // 60
174,  // 61
173,  // 62
172,  // 63
171,  // 64
170,  // 65
169,  // 66
168,  // 67
167,  // 68
166,  // 69
165,  // 70
164,  // 71
163,  // 72
162,  // 73
161,  // 74
160,  // 75
159,  // 76
158,  // 77
157,  // 78
156,  // 79
155,  // 80
154,  // 81
153,  // 82
152,  // 83
151,  // 84
150,  // 85
149,  // 86
148,  // 87
147,  // 88
146,  // 89
145,  // 90
144,  // 91
143,  // 92
142,  // 93
141,  // 94
140,  // 95
139,  // 96
138,  // 97
137,  // 98
136,  // 99
135,  // 100
134,  // 101
133,  // 102
132,  // 103
131,  // 104
130,  // 105
129,  // 106
128,  // 107
127,  // 108
126,  // 109
125,  // 110
124,  // 111
123,  // 112
122,  // 113
121,  // 114
120,  // 115
119,  // 116
118,  // 117
117,  // 118
116,  // 119
115,  // 120
114,  // 121
113,  // 122
112,  // 123
111,  // 124
110,  // 125
109,  // 126
108,  // 127
107,  // 128
106,  // 129
105,  // 130
104,  // 131
103,  // 132
102,  // 133
101,  // 134
100,  // 135
99,  // 136
98,  // 137
97,  // 138
96,  // 139
95,  // 140
94,  // 141
93,  // 142
92,  // 143
91,  // 144
90,  // 145
89,  // 146
88,  // 147
87,  // 148
86,  // 149
85,  // 150
84,  // 151
83,  // 152
82,  // 153
81,  // 154
80,  // 155
79,  // 156
78,  // 157
77,  // 158
76,  // 159
75,  // 160
74,  // 161
73,  // 162
72,  // 163
71,  // 164
70,  // 165
69,  // 166
68,  // 167
67,  // 168
66,  // 169
65,  // 170
63,  // 171
61,  // 172
59,  // 173
57,  // 174
55,  // 175
53,  // 176
51,  // 177
49,  // 178
47,  // 179
45,  // 180
43,  // 181
41,  // 182
39,  // 183
37,  // 184
35,  // 185
33,  // 186
31,  // 187
29,  // 188
27,  // 189
25,  // 190
23,  // 191
21,  // 192
19,  // 193
17,  // 194
15,  // 195
13,  // 196
11,  // 197
9,  // 198
7,  // 199
5,  // 200

};

u16 speedAtLevel[8] = {
	0,
	300,	// 1
	450,	// 2
	600,	// 3
	750,	// 4
	900,	// 5
	1300,	// 6
	1500	// ultraz
};


float dustSenseTab[6] = {
	1.0, 	//no use
	1.0,	// 1
	0.85,	// 2
	0.7,	// 3
	0.55,	// 4
	0.4		// 5
};


#define T_3S  30	// 30*100ms 
#define T_6S  60	// 60*100ms 
#define T_9S  90	// 90*100ms 

#define MAX_TRC_VAR			200
#define MIN_TRC_VAR			20

#define MAX_FAN_SPEED 		1500
#define MIN_FAN_SPEED		80

#define abs(x) ((x>0)?(x):(-x))

s16 fsErr1=0, fsErr2=0;
s8 indErr[11] = {0};
s16 indErr16;
u8 divVar;

u32 saveDataBuf[3];			//(jhb-add for save data to NVM )
u8 saveDataNecessary;	//(jhb)-
u16 saveDataDlyTime;		//(jhb)-
u8 saveDataFinished;	//(jhb)-
///////////////////////////////////////////////////////////////


void simple_uart_config(uint8_t rts_pin_number, uint8_t txd_pin_number, uint8_t cts_pin_number, uint8_t rxd_pin_number, bool hwfc)
{
/** @snippet [Configure UART RX and TX pin] */
    nrf_gpio_cfg_output(txd_pin_number);
    nrf_gpio_cfg_input(rxd_pin_number, NRF_GPIO_PIN_NOPULL);

    NRF_UART0->PSELTXD = txd_pin_number;
    NRF_UART0->PSELRXD = rxd_pin_number;
/** @snippet [Configure UART RX and TX pin] */
	NRF_UART0->CONFIG = 6;
    if (hwfc)
    {
        nrf_gpio_cfg_output(rts_pin_number);
        nrf_gpio_cfg_input(cts_pin_number, NRF_GPIO_PIN_NOPULL);
        NRF_UART0->PSELCTS = cts_pin_number;
        NRF_UART0->PSELRTS = rts_pin_number;
        NRF_UART0->CONFIG  = (UART_CONFIG_HWFC_Enabled << UART_CONFIG_HWFC_Pos);
    }
	
    NRF_UART0->BAUDRATE      = (UART_BAUDRATE_BAUDRATE_Baud19200<< UART_BAUDRATE_BAUDRATE_Pos);
    NRF_UART0->ENABLE        = (UART_ENABLE_ENABLE_Enabled << UART_ENABLE_ENABLE_Pos);
    NRF_UART0->TASKS_STARTTX = 1;
    NRF_UART0->TASKS_STARTRX = 0;
    NRF_UART0->EVENTS_RXDRDY = 0;
//	NRF_UART0->INTENSET =  UART_INTENSET_RXDRDY_Set<<UART_INTENSET_RXDRDY_Pos;
	NRF_UART0->INTENCLR = 0xfffff;

	NVIC_ClearPendingIRQ(UART0_IRQn);
    NVIC_SetPriority(UART0_IRQn, APP_IRQ_PRIORITY_LOW);
    NVIC_EnableIRQ(UART0_IRQn);
	
}


void ApplyIO_Init()
{
	nrf_gpio_cfg_sense_input(PIN_ZERO_INT, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_LOW);
	nrf_gpio_cfg_sense_input(PIN_SPEED,    NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_LOW);
	
	NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_PORT_Enabled << GPIOTE_INTENSET_PORT_Pos;

	//---------------------------------------------------------------------------------
	nrf_gpio_cfg_output(PIN_FAN);
	nrf_gpio_cfg_output(PIN_ION);
	nrf_gpio_cfg_output(PIN_BUZ);
	
	nrf_gpio_cfg_output(PIN_DUST_AD_EN);
	nrf_gpio_cfg_output(PIN_LED1);
	nrf_gpio_cfg_output(PIN_LED2);
	nrf_gpio_cfg_output(PIN_LED3);
	
	//---------------------------------------------------------------------------------
	nrf_gpio_cfg_input(KEYB_D, NRF_GPIO_PIN_NOPULL);
	nrf_gpio_cfg_input(PIN_IR, NRF_GPIO_PIN_PULLUP);	//(ash)
	nrf_gpio_cfg_input(PIN_DUST_AD, NRF_GPIO_PIN_NOPULL);

	
	nrf_gpio_cfg_input(PIN_DUST_SENSTIVE, NRF_GPIO_PIN_PULLUP);	//(jhb)

//    NVIC_SetPriority(GPIOTE_IRQn, APP_IRQ_PRIORITY_HIGH);
//    NVIC_ClearPendingIRQ(GPIOTE_IRQn);
//    NVIC_EnableIRQ(GPIOTE_IRQn);
	//=============================================================
//	simple_uart_config(0, PIN_SDA, 0, PIN_NOT_USED, FALSE);
}

//(ash)
//void Rtc1_init()
//{
//	NRF_CLOCK->TASKS_LFCLKSTART = 1;
//	while(NRF_CLOCK->EVENTS_LFCLKSTARTED == 0);

//	NRF_RTC1->PRESCALER = 0;
//	
//	NVIC_SetPriority(RTC1_IRQn, APP_IRQ_PRIORITY_HIGH);
//    NVIC_ClearPendingIRQ(RTC1_IRQn);
//    NVIC_EnableIRQ(RTC1_IRQn);

//	NRF_RTC1->TASKS_START= 1;
//}

void ZERO_ISR()
{
	volatile u32 counter;
	u16 ccVar;
	
	firstFallFlag  = TRUE;
	if(noSpeedSignalCnt <30) noSpeedSignalCnt++;
	else {
		fspdBk = 0;
		fanSpeed = 0;
	}
	
	if(trcVar > MAX_TRC_VAR) trcVar = MAX_TRC_VAR;
	ccVar = TRC_VAR_TAB[trcVar];
	
	counter = NRF_RTC1->COUNTER;
	counter += ccVar;
	if(counter >= 0xFFFFFF) counter -= 0xFFFFFF;

	if(trcVar <= MIN_TRC_VAR) {
		nrf_gpio_pin_clear(PIN_FAN);
	}else if(trcVar > (MAX_TRC_VAR - 3)) {
		nrf_gpio_pin_set(PIN_FAN);
	}else {
	
		NRF_RTC1->EVENTS_COMPARE[3] = 0;	
		NRF_RTC1->CC[3] = counter;
		NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE3_Enabled << RTC_INTENSET_COMPARE3_Pos;
	}
}


	static u32 lstCnt = 0;
	volatile u32 cnt, spd;

void SPEED_ISR()
{
	
	noSpeedSignalCnt = 0;
	
	cnt = (NRF_RTC1->COUNTER);
	spd = cnt;
	
	if(cnt >= lstCnt) {
		spd = cnt - lstCnt;
	}else {
		spd = cnt + 0xFFFFFF - lstCnt;
	}	
	if(spd < 100) return;
	
	spd = 327680/spd;  // 32768 * 60/6 = 327680;  UNIT RPM
	
	if(spd > 32767) spd = 32767;
	
	fspdBk = (fspdBk + spd)/2;
	fanSpeed = (fspdBk + fanSpeed)/2;


	lstCnt = cnt;
}


//(ash)void RTC1_IRQHandler(void)
void RTC1_COMPARE3_Handler(void)	//(ash)
{
	volatile u32 counter;

	
//(ash)	if(NRF_RTC1->EVENTS_COMPARE[3]) {
		NRF_RTC1->EVENTS_COMPARE[3] = 0;
		
		//----------------------------------------------------
		nrf_gpio_pin_set(PIN_FAN);
		//--------------------------
		if(firstFallFlag) {		
			firstFallFlag = 0;
			counter = NRF_RTC1->COUNTER;
			counter += 328;
			if(counter >= 0xFFFFFF) counter -= 0xFFFFFF;
			
			NRF_RTC1->CC[3] = counter;	//interrupt at about 10ms later
			
		}else {
			NRF_RTC1->INTENCLR = RTC_INTENCLR_COMPARE3_Enabled << RTC_INTENCLR_COMPARE3_Pos;
		}

		delay_10us(50);
		nrf_gpio_pin_clear(PIN_FAN);
//(ash)	}
	
}

const float pidTab[8][3] = {
// based on divVar = 5
	0,0,0,
// 	Kp,   	 Ki,  	  Kd
	15.0,	1.00,	10.0,	// Speed Level 1
	
	15.0,	1.00,	10.0,	// Speed Level 2
	
	15.0,	1.00,	10.0,	// Speed Level 3
	15.0,	1.00,	10.0,	// Speed Level 4
	
	15.0,	1.00,	10.0,	// Speed Level 5
	15.0,	1.00,	10.0,	// Speed Level 6
	
	15.0,	1.00,	10.0,	// Speed Level 7

};

float ek, ek1, ek2;
float u, u1;
float Kp, Ki, Kd;
float ux;

u8 xo1, xo2, xo3, xo4;

void Pid_reset_allDat()
{
//	Kp = 0;
//	Ki = 0;
//	Kd = 0;
	u = 0;
	u1 = 0;
	ek = 0;
	ek1 = 0;
	ek2 = 0;
	xo1 = 0;
	xo2 = 0;
	xo3 = 0;
	xo4 = 0;

	divVar = 5;
}

void Pid_K_Update()
{
	if(fanSpeedLevel <8 ) {
		Kp = pidTab[fanSpeedLevel][0];
		Ki = pidTab[fanSpeedLevel][1];
		Kd = pidTab[fanSpeedLevel][2];
	}
}


void PidCtrl1()
{
	float pErr=0;
	float iErr=0;
	float dErr=0;

	ek = (float)((float)targetFanSpeed - (float)fanSpeed);
	pErr = ek - ek1;
	iErr = ek;
	dErr = ek - ek1*2 + ek2;
	ek2 = ek1;
	ek1 = ek;
	
	u = Kp*pErr + Ki*iErr + Kd*dErr + u1;

//	if(fanSpeed==0 && u < -1000) u = 0;
	if(u > 20000) u = 20000;
	if(u< -2000) u= -2000;	
	
	u1 = u;
	ux = u/100;
	
	if(ux<=0) xo1 = 0;
	else if(ux < MAX_TRC_VAR) xo1 = ux;
	else xo1 = MAX_TRC_VAR;

	xo2 = ((u16)xo1 + (u16)xo2)/2;
	xo3 = ((u16)xo2 + (u16)xo3)/2;
	xo4 = ((u16)xo3 + (u16)xo4)/2;

	trcVar = xo2;
	
}


void FanSpeedControl()
{
	static u8 div = 0;


	if(++div < divVar) return;
	div = 0;

	
	if(targetFanSpeed < MIN_FAN_SPEED) {
		trcVar = 0;
		return;
	}	
	if(targetFanSpeed > MAX_FAN_SPEED) targetFanSpeed = MAX_FAN_SPEED;
	
	//-------------------------------------------------------------------------------------------
	Pid_K_Update();
	PidCtrl1();

	
}


////////////////////////////////////////////////////////////////


void Application_Init(void)
{
	RTC1_SetCOMPARE3Handler(RTC1_COMPARE3_Handler);	//(ash)

	Clk_Init();

	ApplyIO_Init();

	Keyb_Init();
#ifdef REMOTE_IR
	IR_Init();
#endif

	//(ash)
    NVIC_SetPriority(GPIOTE_IRQn, APP_IRQ_PRIORITY_HIGH);
    NVIC_ClearPendingIRQ(GPIOTE_IRQn);
    NVIC_EnableIRQ(GPIOTE_IRQn);
	//

//(ash)	Rtc1_init();
	Buz_Init();
	Adc_init();

	DisplayPinInit();

	sysState = SYS_OFF;
	timerOff_minute_set = timerOff_minute = 0;	//(ash) timerOff_minute_set =
	aqiHighSense = FALSE;
	
//(ash)	
//	fanSpeedLevel = FAN_OFF;
//	handFspLevel = FAN_OFF;
//	ionEnable = FALSE;
//	targetFanSpeed = 0;

	//(ash)
	workingMode = MODE_HAND;
	fanSpeedLevel = handFspLevel = FAN_SPD3;
	ionEnable = TRUE;
	rAQI = AQI_VERY_EXECLLENT;

	InitDataFromFlash();	//replaced by jhb
	

	if(workTime_seconds > (2000*3600)){
		filterNeedReplace = TRUE;
	}else {
		filterNeedReplace = FALSE;
	}

	
}





u16 miDivCnt = 0;
void TimeEvent(void)
{
	if(flag_100ms) {
		flag_100ms = FALSE;
		//--------------------------------------
		if(haltTime) haltTime--;
	}
	//===========================================
	if(flag_500ms) {
		flag_500ms = FALSE;
		//-----------------------------------
		
	}

	//===========================================
	if(flag_1s) {
		flag_1s = FALSE;
		
    	miDivCnt++;
    	//GetTemp();
		//---------------------------------------------
		if(pairing) {
			if(++pairStateCnt > 15) {
				pairStateCnt = 0;
				pairing = FALSE;
			}
		}
		//------------------------------------

		//------------------------------------
		if(noUserActiveCnt < 120) noUserActiveCnt++;
		//------------------------------------
		if(waitTime) {
			waitTime--;
			if(waitTime ==0) {
						
			}
		}
		//-----------------------------------------------
		if(++second >= 60) {
			second  = 0;
			//----------------------
			if(timerOff_minute) {
				if(--timerOff_minute ==0) {
					sysState = SYS_OFF;	
				}
				
			}

		}

	}


	//----------------------------------------------------------------------------------------
	if(miDivCnt >= (60*60)) {	// 60 minute	(ash) 5min->60min
		miDivCnt = 0;
		//-------------------------------
		if(sysState == SYS_ON) { // only in working 
			
			if(filterNeedReplace == FALSE) {
				workTime_seconds += 3600;	//(ash) 300->3600
				TrigSaveData(200);	// 2秒后写入FLASH
			}
			//------------------------------------------
			if(workTime_seconds > (3600*2000)){ 
				if(filterNeedReplace == FALSE) {
					Beep(3, 30);
				}
				filterNeedReplace = TRUE;
				
			}else {
				filterNeedReplace = FALSE;
			}
		}
	}

	//----------(lcx) add--------
	
	if(setDustSenseLevel == FALSE  && lstDustSenseLevel != dustSenseLevel) {
		TrigSaveData(200);	// 2秒后写入FLASH
		lstDustSenseLevel = dustSenseLevel;
	}
	
	//---------------------------
}



void DustSenstiveCheck()
{
	u8 pin;
	static u8 divcnt1 = 0;

	pin = nrf_gpio_pin_read(PIN_DUST_SENSTIVE);
	if(pin ==0) {
		if(++divcnt1 >= 50){
			divcnt1 = 50;
			aqiHighSense = TRUE;
		}
	}else {
		if(divcnt1)divcnt1--;
		else {
			aqiHighSense = FALSE;
		}
	}
	
}



//------------------------------------------------------------------------------
// DUST DETECT 
#define WORST_VAR  		(u16)351		//(488*3.6/5)
#define BEST_VAR   		(u16)58			//(488*0.6/5)
#define LEVEL_DEGREE  	(u16)49			//((WORST_VAR - BEST_VAR)/6)



u16 adbuf[6];
u16 dustVar;
u16 aqiLevelDegree;

extern u16 ad1;
void DustDetect()
{
	u8 i;
	u16 maxVar = 0;
	static u16 dustVar_bk1=0, dustVar_bk2=0;
	static u32 sum32 = 0;
	static u8 cnt = 0;
	
	nrf_gpio_pin_set(PIN_DUST_AD_EN);
	for(i= 0; i<6; i++) {
		AdConver();
 		adbuf[i] = ad1;
	}
	nrf_gpio_pin_clear(PIN_DUST_AD_EN);
	//-----------------------------------------------------
	for(i=0; i<6; i++) {
		if(adbuf[i] > maxVar) maxVar = adbuf[i];
	}
	//-----------------------------------------------------------
	//(JHB)
	if(setDustSenseLevel == FALSE) {  // (lcx) add
		dustSenseFactor = dustSenseTab[dustSenseLevel];
	}
	aqiLevelDegree = LEVEL_DEGREE*dustSenseFactor; // (lcx) add
	/*
	if(aqiHighSense) {  //以检测为准还是以设定为准??	
		aqiLevelDegree = LEVEL_DEGREE*0.7;
	}else {
		// (lcx) aqiLevelDegree = LEVEL_DEGREE; 
		aqiLevelDegree = LEVEL_DEGREE; 
		//aqiLevelDegree = LEVEL_DEGREE*dustSenseFactor; // (lcx) add
	}
	*/
	//------------------------------------------------------------
	sum32 += maxVar;
	
	if(++cnt >= 200) {
		cnt = 0;
		dustVar_bk1 += (u16)(sum32/200);
		
		sum32 = 0;
		dustVar_bk1/=2;

		dustVar_bk2 = (dustVar_bk2 + dustVar_bk1)/2;
		dustVar 	= (dustVar + dustVar_bk2)/2;
		
		//-----------------------------------------------------------
		if(dustVar < BEST_VAR + (1*aqiLevelDegree)) {
			rAQI = AQI_VERY_EXECLLENT;
			
		}else if(dustVar < BEST_VAR + (2*aqiLevelDegree)) {
			rAQI = AQI_EXECLLENT;
			
		}else if(dustVar < BEST_VAR + (3*aqiLevelDegree)) {
			rAQI = AQI_VERY_GOOD;
			
		}else if(dustVar < BEST_VAR + (4*aqiLevelDegree)) {
			rAQI = AQI_GOOD;
			
		}else if(dustVar < BEST_VAR + (5*aqiLevelDegree)) {
			rAQI = AQI_BAD;
			
		}else if(dustVar < BEST_VAR + (6*aqiLevelDegree)) {
			rAQI = AQI_VERY_BAD;
		}
		
	}

	
}


void OutPutCtrl(void)
{
	if(sysState == SYS_OFF) {
		targetFanSpeed = 0;
		trcVar = 0;
		Pid_reset_allDat();
		nrf_gpio_pin_clear(PIN_ION);
		nrf_gpio_pin_clear(PIN_FAN);
		return;
	}	
	
	targetFanSpeed = speedAtLevel[fanSpeedLevel];
	
	if(ionEnable) nrf_gpio_pin_set(PIN_ION);
	else nrf_gpio_pin_clear(PIN_ION);
}



////////////////////////////////////////////////////////////////

void Application(void)
{
	if(sysState == SYS_OFF) {
		return;
	}
	//==========================================
	switch(workingMode) {
		case MODE_HAND:
			fanSpeedLevel = handFspLevel;
			if(fanSpeedLevel > FAN_SPD6) fanSpeedLevel = FAN_SPD6;
			
			
			break;
		//----------------------------
		case MODE_AUTO:
			if(rAQI == AQI_VERY_EXECLLENT) 	fanSpeedLevel = FAN_SPD1;
			if(rAQI == AQI_EXECLLENT) 		fanSpeedLevel = FAN_SPD2;
			if(rAQI == AQI_VERY_GOOD) 		fanSpeedLevel = FAN_SPD3;
			if(rAQI == AQI_GOOD) 			fanSpeedLevel = FAN_SPD4;
			if(rAQI == AQI_BAD) 			fanSpeedLevel = FAN_SPD5;
			if(rAQI == AQI_VERY_BAD) 		fanSpeedLevel = FAN_SPD6;
			
			break;
		//----------------------------
		case MODE_SMOKE:
			fanSpeedLevel = FAN_SPD6;
			
			break;
		//----------------------------
		case MODE_NIGHT:
			fanSpeedLevel = FAN_SPD1;
			
			break;
		//----------------------------
		default: break;
	}
	
	//==========================================
	if(workTime_seconds >= 2000*3600){
		filterNeedReplace = TRUE;
	}else filterNeedReplace = FALSE;


}


////////////////////////////////////////////////////////////////

//API for R4S

//The all Set...() functions return a true/false (Success/Fail) value

////////////////////////////////////////////////////////////////

//Get firmvare version
u16 API_GetVersion(void)
{
	return FIRMWARE_VER;
}


bool API_On(void)						//On device
{
	if(sysState != SYS_OFF) return FALSE;
	
	noUserActiveCnt = 0;
	sysState = SYS_ON;

	return TRUE;
}

bool API_Off(void)						//Off device
{
	if(sysState == SYS_OFF && !pairing) return FALSE;

	timerOff_minute_set = timerOff_minute = 0;	//(ash)

	pairing = FALSE;
	sysState = SYS_OFF;
	return TRUE;
}

u8 API_GetState(void)				//Get device state
{
	u8 res;
	
	if(sysState == SYS_OFF) res = API_OFF_STATE;
	else {
		res = API_WORK_STATE;
	}
//(ash)	if(errorId)  res = API_ERROR_STATE;
	if(pairing)  res = API_PAIRING_STATE;
	if(testMode) res = API_TEST_STATE;

	return res;
}

bool API_SetMode(uint8_t mode)				//Set mode
{
//(ash)
//	if(sysState == SYS_OFF) return FALSE;

//	if(mode == API_HAND_MODE)  workingMode = MODE_HAND;
//	if(mode == API_AUTO_MODE)  workingMode = MODE_AUTO;
//	if(mode == API_SMOKE_MODE) workingMode = MODE_SMOKE;
//	if(mode == API_NIGHT_MODE) workingMode = MODE_NIGHT;
//	
//	return TRUE;

	//(ash)
	if(mode == API_HAND_MODE)	{workingMode = MODE_HAND; return TRUE;}
	if(mode == API_AUTO_MODE)	{workingMode = MODE_AUTO; return TRUE;}
	if(mode == API_SMOKE_MODE)	{workingMode = MODE_SMOKE; return TRUE;}
	if(mode == API_NIGHT_MODE)	{
			workingMode = MODE_NIGHT;
			timerOff_minute_set = timerOff_minute = 0;	//(ash 16.06.2015)
			return TRUE;
	}
	return FALSE;
	//
}

//Get mode
u8 API_GetMode(void)				
{
//(ash)
//	u8 res = API_HAND_MODE;
//	
//	if(sysState == SYS_ON) {
//		if(workingMode == MODE_HAND)  res = API_HAND_MODE;
//		if(workingMode == MODE_AUTO)  res = API_AUTO_MODE;
//		if(workingMode == MODE_SMOKE) res = API_SMOKE_MODE;
//		if(workingMode == MODE_NIGHT) res = API_NIGHT_MODE;
//	}
//	
//	return res;

	//(ash)
	if(workingMode == MODE_HAND)  return API_HAND_MODE;
	if(workingMode == MODE_AUTO)  return API_AUTO_MODE;
	if(workingMode == MODE_SMOKE) return API_SMOKE_MODE;
	if(workingMode == MODE_NIGHT) return API_NIGHT_MODE;
	return API_HAND_MODE;
	//
}


//Set speed
bool API_SetSpeed(u8 spdLevel)				
{
//(ash)
//	bool res = FALSE;
//	
//	if(sysState == SYS_ON) {
//		if(spdLevel > FAN_SPD6) res = FALSE;
//		else {
//			fanSpeedLevel = spdLevel;
//			res = TRUE;
//		}
//	}

//	return res;

	//(ash)
	if(spdLevel == 0) return TRUE;
	if(spdLevel > FAN_SPD6) return FALSE;

	if(workingMode != MODE_HAND) return FALSE;
	fanSpeedLevel = handFspLevel = spdLevel;
	return TRUE;
	//
}

//Get speed
u8 API_GetSpeed(void)				
{
//(ash)	if(sysState == SYS_OFF) return 0;
	return fanSpeedLevel;
}


//Set work timer in hours
bool API_SetTimer(u8 hour)				
{
//(ash)	if(sysState == SYS_OFF) return FALSE;
//(ash)	timerOff_minute = hour * 60; //

	//(ash)
	if(hour > 8) return FALSE;

	timerOff_minute_set = hour * 60;
	if(sysState == SYS_ON) timerOff_minute = timerOff_minute_set;
	//

	return TRUE;
}

//Get work timer in hours
u8 API_GetTimer(void)				
{
//(ash)
//	u8 res = 0;
//	
//	if(timerOff_minute==0) res = 0;
//	else if(timerOff_minute <= 2*60) res = 2;	
//	else if(timerOff_minute <= 4*60) res = 4;	
//	else if(timerOff_minute <= 6*60) res = 6;	
//	else if(timerOff_minute <= 8*60) res = 8;		

//	return res;

	return timerOff_minute_set / 60;	//(ash)
}


u16 API_GetEndTime(void)			//Get time to end of work in minutes
{
//(ash)	if(sysState == SYS_OFF) return 0;
	return timerOff_minute;
}


bool API_SetIon(u8 ionEn)				//Set ionisation state (ON/OFF)
{
//(ash)	if(sysState == SYS_OFF) return FALSE;

	if(ionEn != 1 && ionEn != 0) return FALSE;	//(ash)
	if(workingMode == MODE_NIGHT) return FALSE;	//(ash)

	if(ionEn) ionEnable = 1;
	else ionEnable = 0;

	return TRUE;
}

u8 API_GetIon(void)				//Get ionisation state (ON/OFF)
{
//(ash)	if(sysState == SYS_OFF) return FALSE;
	return ionEnable;
}

//(ash)
//Get air quality
u8 API_GetAirQuality(void)
{
	return rAQI;
}
//

//Return a state of the unpairing flag
bool API_IsUnpairing(void)
{
	return unpairingFlag;
}


//Clear unpairing flag
void API_ClrUnpairing(void)
{
	unpairingFlag = FALSE;
}


u8 API_GetError(void)			//Get error number	(ash) u16->u8
{
	return errorId;
}

////////////////////////////////////////////////////////////////
//
//(jhb)add
void InitDataFromFlash(void)
{
	u8* volatile p;
	u16 i = 0;

	
	dustSenseLevel = *((u32 *)(FLASH_ADDR_dustSenseLevel));	//(lcx) add ---
	workTime_seconds = *((u32 *)(FLASH_ADDR_totalTime));	//(ash) u16 -> u32
	
	if((dustSenseLevel < DUST_SENSE_LEV1)||(dustSenseLevel > DUST_SENSE_LEV5)) {
		dustSenseLevel = DUST_SENSE_LEV3;
		i++;
	} 
	dustSenseFactor = dustSenseTab[dustSenseLevel];
	lstDustSenseLevel = dustSenseLevel;
	//----------------------------------------------------------------------------

	//-----------------------------------------------------------------------------------
	
	if(workTime_seconds == 0xffffffff) { // not initialed //(jhb) 0xffff -> 0xffffffff
		workTime_seconds = 0;
		i++;
	}

	if(i>0) {//need to write new initial value
		u32 result;	
		do result = sd_flash_page_erase(FLASH_ADDR_totalTime/FLASH_PAGE_SIZE); while(result != NRF_SUCCESS);
		do result = sd_flash_write((u32*)FLASH_ADDR_totalTime, &workTime_seconds, 1); while(result != NRF_SUCCESS);	
		do result = sd_flash_write((u32*)FLASH_ADDR_dustSenseLevel, &dustSenseLevel, 1); while(result != NRF_SUCCESS);	
	}

}


//------------------------------------------------------
//timeDly4Save 单位是10ms
void TrigSaveData(u16 timeDly4Save)
{
//	saveDataBuf[0] = workTime_seconds;
//	saveDataBuf[1] = dustSenseLevel;
		
	saveDataDlyTime 	= timeDly4Save;		// 3秒之后写入
	saveDataNecessary	= TRUE;	
	saveDataFinished 	= FALSE;	
}


void UserDataSave2FlashProcess(void)
{
	if(saveDataDlyTime){
		saveDataDlyTime--;
		return;
	}
	//--------------------------------------------------
	if(saveDataNecessary != TRUE) return;
	if(saveDataFinished == TRUE) return;
	//--------------------------------------------------
	{
		u32 result;
		//(lcx) u32 t32 = (u32)&saveDataBuf;
		do result = sd_flash_page_erase(FLASH_ADDR_totalTime/FLASH_PAGE_SIZE); while(result != NRF_SUCCESS);
		do result = sd_flash_write((u32*)FLASH_ADDR_totalTime, &workTime_seconds, 1); while(result != NRF_SUCCESS);	
		do result = sd_flash_write((u32*)FLASH_ADDR_dustSenseLevel, &dustSenseLevel, 1); while(result != NRF_SUCCESS);	

		saveDataFinished = TRUE;
		saveDataNecessary = FALSE;
	}
}

Made on
Tilda