/** * переключение датчика на текущий цвет и сброс таймера для нового замера * @global tcsColor -- текущий цвет замера */ void tcsNextColor(){ uint8_t color = tcsColor+2; // изменяем порядок цветов: первым опрашиваем общий канал! if( color & 2 ){ pinOutHigh(tcsS2); }else{ pinOutLow(tcsS2); } if( color & 1 ){ pinOutHigh(tcsS3); }else{ pinOutLow(tcsS3); } timerCount(tcsTimer) = 0; }
/** * КА датчика: замеры цвета, пересчеты, коррекции и сохранение результата * Устанавливается как хук таймера и вызывается каждые 1024мксек. */ void tcsRun() { if( tcsColor == TCS_NOCOLOR ) return; // не запущен замер/останов, выход. if( tcsColor == TCS_START ) { // начало очередного замера uint8_t c; tcsColor = tcsMeasure = tcsIsBright = 0; for(c=0; c<4; c++) tcsTemp[c] = 0; tcsCurWait = tcsWait; // устанавливаем сколько тиков будем считать счетчик }else{ if( --tcsCurWait > 0 ) return; // ещё рано. // замер: приводим текущий замер к эфф. времени uint16_t counter = timerCount(tcsTimer); counter *= (TCS_MAX_WAIT / tcsWait); // масшабируем счетчик: как-бы считали TCS_MAX_WAIT tcsTemp[tcsColor] += counter; if( counter > 599*TCS_MAX_WAIT ){ tcsIsBright = 1; } // Очень ярко! Частота выше 600кГц !!! if( tcsColor == 0 && !(tcsModes & TCS_SPEED_CONST) ){ // первым замеряли яркостный канал: смотрим надо ли менять время замеров (удерживаем точность 0.5%): if( counter < 150 ){ tcsWait = TCS_WAIT * 4; } // совсем темно, макс. длительность. else if( counter < 300 ){ tcsWait = TCS_WAIT * 2; } // темновато, удвоенная длительность. else if( tcsWait>1 ){ tcsWait /= 2; } // пробуем сократить время замера } tcsCurWait = tcsWait; // установка времени в хуке заново. if( (tcsModes & TCS_WB_ONLY) || (++tcsColor) == TCS_NOCOLOR ){ tcsColor = TCS_NOCOLOR; if( tcsMeasure >= TCS_MAX_MEASURES-1 ) // Завершены все попытки: { if( tcsModes & TCS_WB_ONLY ){ tcsTemp[0] /= TCS_MAX_MEASURES; // .. ч/б режим: только усреднение, нет коррекций! }else{ if( !(tcsModes & TCS_NOT_CORRECT) ) tcsCorrect(); // .. восстанавливаем баланс белого (R=0.18%,G=0.41%,B=-0.05%) if( !(tcsModes & TCS_NOT_AVERAGE) ) tcsAvg(); // .. усредняем цвет if( !(tcsModes & TCS_NOT_WHITE) ) tcsWhiteLocal(); // .. коррекция баланса белого от внутренних светодиодов if( !(tcsModes & TCS_NOT_CONTRAST) ) tcsContrast(); // .. повышение контрастности цветов } if( !(tcsModes & TCS_NOT_LUKSES) ) tcsLukses(); // .. масштабируем частоту в люксы tcsRaw(); // .. переносим значения в результат tcsCount++; // .. конец работы, новый номер замера. return; }else{ tcsMeasure++; tcsColor = 0; } } } // if !START tcsNextColor(); }
// метод "шаг цикла КА" в микросекундах по 4мксек [0,4,..1024мксек]: // параметр - указатель на состояние заданного КА. void tsc_microStep( TSC_Control *_tsc ) { // если задана таблица (нет - выключен!) if( _tsc->table ){ // если событие, переключающее КА - наступило: if( (((TSC_Time)timerCount(0))<<2) - _tsc->started_at >= _tsc->timeout ) { // определяем место хранения структуры состояния КА const TSC_Step * current PROGMEM = _tsc->table + _tsc->state; // читаем и исполняем команду и получаем номер следующего состояния или нуль(+=1): TSC_Command command = (TSC_Command)pgm_read_word_near( &(current->command) ); TSC_Step_Count next = (TSC_Step_Count)pgm_read_word_near( &(current->next) ); // и сразу устанавливаем следующий шаг КА и начало периода tsc_next(_tsc, next); // исполнение команды - последним. Её время выполнения ВХОДИТ в ожидание, // допускается вызов tsc_next() из самой команды - принудительная смена состояния в команде if( command ) { command(_tsc); } } } }