#include "BulbId.h" #include "BulbId_cfg.h" #include "PWM.h" #include "string.h" #include "intrins.h" #include "math.h" #include "task.h" #define BULB_INFO_CNT 2 #define BULB_INFO_SIZE 9 XDATA uint8_t BulbInfo[BULB_INFO_CNT][BULB_INFO_SIZE]; XDATA struct BulbId bulbId; // MiLight CCT bulbs range from 2700K-6500K, or ~370.3-153.8 mireds. #define COLOR_TEMP_MAX_MIREDS 370 #define COLOR_TEMP_MIN_MIREDS 153 static uint8_t rescale(uint16_t value, uint16_t newMax, float oldMax) { float r = ((value * (newMax / oldMax))+0.5f); return (uint8_t)r; } static uint16_t whiteValToMireds(uint8_t value, uint8_t maxValue) { uint16_t scaled = rescale (value, (COLOR_TEMP_MAX_MIREDS - COLOR_TEMP_MIN_MIREDS), maxValue); return COLOR_TEMP_MIN_MIREDS + scaled; } uint8_t constrain(uint8_t in,uint8_t min,uint8_t max) { uint8_t r = 0; if(in max) r = max; return r; } uint16_t hiteValToMireds(uint8_t value, uint8_t maxValue) { uint16_t scaled = rescale(value, (COLOR_TEMP_MAX_MIREDS - COLOR_TEMP_MIN_MIREDS), maxValue); return COLOR_TEMP_MIN_MIREDS + scaled; } static void decodeCmd(uint8_t *pBulbInfo,uint8_t len1) { uint8_t *packetCopy = pBulbInfo; uint8_t command = (packetCopy[V2_COMMAND_INDEX] & 0x7F); uint8_t arg = packetCopy[V2_ARGUMENT_INDEX]; uint16_t deviceId = (packetCopy[V2_ID_HI_INDEX ] << 8) | packetCopy[V2_ID_LOW_INDEX ]; uint8_t groupId = packetCopy[V2_GRP_INDEX ]; if(!bulbId.bInit) { bulbId.deviceId = deviceId; bulbId.groupId = groupId; bulbId.deviceType = REMOTE_TYPE_FUT089; } if(bulbId.deviceId==deviceId) { switch(command) { case FUT089_ON: if ((packetCopy[V2_COMMAND_INDEX] & 0x80) == 0x80) { bulbId.result.COMMAND = NIGHT_MODE; } else if (arg == FUT089_MODE_SPEED_DOWN) { bulbId.result.COMMAND = MODE_SPEED_DOWN; } else if (arg == FUT089_MODE_SPEED_UP) { bulbId.result.COMMAND = MODE_SPEED_UP; } else if (arg == FUT089_WHITE_MODE) { bulbId.result.COMMAND = SET_WHITE; } else if (arg <9) { // Group is not reliably encoded in group byte. Extract from arg byte bulbId.result.STATE = ON ; bulbId.groupId = arg; } else if (arg > 10 && arg < 18) { bulbId.result.STATE = OFF ; bulbId.groupId = arg-9; } break; case FUT089_COLOR: { uint8_t rescaledColor = (arg - FUT089_COLOR_OFFSET) % 0x100; uint16_t hue = rescale(rescaledColor, 360, 255.0); bulbId.result.HUE = hue; } break; case FUT089_BRIGHTNESS: { uint8_t level = constrain(arg, 0, 100); bulbId.result.BRIGHTNESS = rescale (level, 255, 100); } break; case FUT089_SATURATION: //饱和度 { /* //const GroupState* state = stateStore->get(bulbId); //if (state != NULL && state->getBulbMode() == BULB_MODE_COLOR) { bulbId.result.SATURATION = 100 - constrain(arg, 0, 100); } //else { bulbId.result.COLOR_TEMP = whiteValToMireds(100 - arg, 100); } */ } break; case FUT089_MODE: bulbId.result.MODE = arg; break; default: break; } bulbId.result.button_id = command; bulbId.result.argument = arg; _nop_(); } UNUSED(len1); } void SetLEDState(uint8_t state) { CONST uint16_t pPwmInfo_Low[5] = {0,0,0,0,0}; CONST uint16_t pPwmInfo_Hi[5] = {0xFF,0xFF,0xFF,0xFF,0xFF}; SetPWMInfo( state?pPwmInfo_Hi:pPwmInfo_Low,sizeof(pPwmInfo_Low)/sizeof(uint16_t)); } XDATA uint8_t BlinkLEDCnt = 0; #if TASK_WITH_PT PT_THREAD(TaskBlinLed(struct pt *pt1 )) #else PT_THREAD(TaskBlinLed(void)) #endif { static XDATA struct timer input_timer; //一定要绑定,不然是个野指针 #if(!TASK_WITH_PT) struct pt *pt1 ; PT_BIND(pt1); #endif _nop_(); PT_BEGIN(pt1); PT_INIT(pt1); while(1) { timer_set(&input_timer,100); //LED = 1; SetLEDState(1); PT_WAIT_UNTIL(pt1, timer_expired(&input_timer)); _nop_(); timer_set(&input_timer,900); //LED = 0; SetLEDState(0); PT_WAIT_UNTIL(pt1, timer_expired(&input_timer)); _nop_(); BlinkLEDCnt--; if(BlinkLEDCnt==0) { SuspendTask(TASK_ID(TaskBlinLed)); PT_EXIT(pt1); } } PT_END(pt1); } void StartBlinkLED(uint8_t cnt) { BlinkLEDCnt = cnt; ActiveTask(TASK_ID(TaskBlinLed),10); } //链接代码:关灯后等待10秒再打开,然后在灯亮时3秒内短按“I”按钮3次,灯光缓慢闪烁3次表示链接成功。(实际为10s) //解绑代码:类似链接操作,但需在灯亮时3秒内短按“I”按钮5次,灯光快速闪烁10次表示解绑成功。(实际为10s) int8_t InitTimer = -1; void InitOrUninit(void* p) { if(InitTimer>=0) { if(bulbId.bInit) { if(bulbId.repeatCnt>=5) { bulbId.bInit = 0; //解绑 StartBlinkLED(10); bulbId.repeatCnt = 0; StopTimer(&InitTimer); //TODO:写入EEPROM } } else { if(bulbId.repeatCnt>=3) { bulbId.bInit = 1; //绑定 StartBlinkLED(3); bulbId.repeatCnt = 0; StopTimer(&InitTimer); //TODO:写入EEPROM } } } UNUSED(p); } //等待初始化 void waitForInitOrUnInit(void) { StartTimer2(&InitTimer,TIMER_MODE_TIMER,10000,NULL,NULL); _nop_(); } uint8_t GetRepeatCnt(uint8_t curIndex,uint8_t preIndex) { uint8_t bCompMemValue = memcmp(BulbInfo[curIndex],BulbInfo[preIndex],6); uint8_t bCompGrp =(BulbInfo[curIndex][V2_GRP_INDEX]==BulbInfo[preIndex][V2_GRP_INDEX]); CONST uint8_t maxv = (1U<<3)-1; if( (bCompMemValue==0)&&bCompGrp ) { if(bulbId.repeatCnt(), 100, 255)); changes |= stateChange; } if (isOn() && state.containsKey(GroupStateFieldNames::HUE)) { changes |= setHue(state[GroupStateFieldNames::HUE]); changes |= setBulbMode(BULB_MODE_COLOR); } if (isOn() && state.containsKey(GroupStateFieldNames::SATURATION)) { changes |= setSaturation(state[GroupStateFieldNames::SATURATION]); } if (isOn() && state.containsKey(GroupStateFieldNames::MODE)) { changes |= setMode(state[GroupStateFieldNames::MODE]); changes |= setBulbMode(BULB_MODE_SCENE); } if (isOn() && state.containsKey(GroupStateFieldNames::COLOR_TEMP)) { changes |= setMireds(state[GroupStateFieldNames::COLOR_TEMP]); changes |= setBulbMode(BULB_MODE_WHITE); } if (state.containsKey(GroupStateFieldNames::COMMAND)) { const String& command = state[GroupStateFieldNames::COMMAND]; if (isOn() && command == MiLightCommandNames::SET_WHITE) { changes |= setBulbMode(BULB_MODE_WHITE); } else if (command == MiLightCommandNames::NIGHT_MODE) { changes |= setBulbMode(BULB_MODE_NIGHT); } else if (isOn() && command == "brightness_up") { changes |= applyIncrementCommand(GroupStateField::BRIGHTNESS, IncrementDirection::INCREASE); } else if (isOn() && command == "brightness_down") { changes |= applyIncrementCommand(GroupStateField::BRIGHTNESS, IncrementDirection::DECREASE); } else if (isOn() && command == MiLightCommandNames::TEMPERATURE_UP) { changes |= applyIncrementCommand(GroupStateField::KELVIN, IncrementDirection::INCREASE); changes |= setBulbMode(BULB_MODE_WHITE); } else if (isOn() && command == MiLightCommandNames::TEMPERATURE_DOWN) { changes |= applyIncrementCommand(GroupStateField::KELVIN, IncrementDirection::DECREASE); changes |= setBulbMode(BULB_MODE_WHITE); } } if (changes) { debugState("GroupState::patch: State changed"); } else { debugState("GroupState::patch: State not changed"); } return changes; } */