19 #include <avr_helper.h> 22 #include <avr/pgmspace.h> 26 #include "avr_helper.h" 30 #include <util/delay.h> 33 #if !defined(DISABLE_SD_SCRIPT) 39 #define enter_sd_mode() do { SPCR = _BV(SPE) | _BV(MSTR); PORT(WS_LOCK_PORT) &= ~WS_LOCK_PIN;} while(0) 41 #define leave_sd_mode() do { SPCR = _BV(SPE) | _BV(MSTR) | _BV(CPHA); SPDR=0; while(!(SPSR & (1<<SPIF))); PORT(WS_LOCK_PORT) |= WS_LOCK_PIN; } while(0) 43 #define MODULE_NAME "SCRIPT PLAYER" 45 static __flash
const char _name[] = MODULE_NAME;
59 #define SD_BUF_SZ 256UL 74 static uint16_t get_script_count(
void);
80 static void script_exec(
signal_t *s);
82 static int8_t select_next = 0;
107 static uint16_t total_script_files;
109 static uint16_t script_id;
121 if(pf_mount(&fs) == FR_OK){
123 if(pf_opendir(&dir,
"") == FR_OK){
136 static uint16_t get_script_count(
void){
142 res = pf_readdir(&dir, 0);
146 res = pf_readdir(&dir, &file);
148 if (res || !file.fname[0])
break;
151 if (!(file.fattrib & (AM_DIR|AM_HID)) && strstr(file.fname,
".SC"))
169 res = pf_readdir(&dir, 0);
171 res = pf_readdir(&dir, &file);
172 if (res || !file.fname[0])
break;
173 if (!(file.fattrib & (AM_DIR|AM_HID)) && strstr(file.fname,
".SC"))
id--;
174 }
while(
id && (res == FR_OK));
183 strncpy(s->
filename, file.fname, 12);
199 if(pf_lseek(s->
pos) == FR_OK){
207 while(n && str[b] && (str[b] !=
' ') && (str[b] !=
'\n') && (str[b] !=
'\r') && (str[b] !=
'\t')) {
239 static uint8_t get_script_digit(
char *str){
240 if((str[0] >=
'0') && (str[0] <=
'9'))
return str[0] -
'0';
241 else if((str[0] >=
'A') && (str[0] <=
'F'))
return str[0] -
'A' + 10;
245 #define ERROR_CH 0xFF00 253 static uint16_t get_script_val(
char *str){
257 uint8_t n = get_script_digit(++str);
260 }
else if (str[0] ==
'R'){
262 if(str[1] ==
'D')
return rand() & 0x00FF;
263 else if(str[1] ==
'P')
return rand() %
PIXEL_CNT;
264 else return ERROR_CH;
265 }
else if (str[0] ==
'T'){
268 else return ERROR_CH;
271 uint8_t nh = get_script_digit(str++);
272 uint8_t nl = get_script_digit(str);
273 if((nh < 0x10) && (nl < 0x10))
return (nh << 4) | nl;
274 else return ERROR_CH;
282 static uint32_t popstack(
void){
298 static void pushstack(uint32_t d){
311 static uint8_t execute_cmd(
char *cmd){
318 uint8_t n = get_script_digit(cmd+1);
321 tmp = get_script_val(cmd+3);
325 case '=': param.
var[n] = tmp;
break;
326 case '+': tmp += param.
var[n]; param.
var[n] = tmp > 255 ? 255 : tmp;
break;
327 case '-': tmp = param.
var[n] - tmp; param.
var[n] = tmp < 0 ? 255: tmp;
break;
328 case '*': tmp *= param.
var[n]; param.
var[n] = tmp > 255 ? 255 : tmp;
break;
329 case '/':
if(tmp == 0)
return 0;
332 case '%':
if(tmp == 0)
return 0;
350 tmp = get_script_val(cmd+3);
353 if(strncmp_P(cmd, PSTR(
"PB"), 2) == 0){
357 }
else if(strncmp_P(cmd, PSTR(
"GB"), 2) == 0){
362 }
else if(strncmp_P(cmd, PSTR(
"PF"), 2) == 0){
366 }
else if(strncmp_P(cmd, PSTR(
"GF"), 2) == 0){
371 }
else if(strncmp_P(cmd, PSTR(
"PC"), 2) == 0){
373 uint16_t tmp2 = get_script_val(cmd+5);
374 uint16_t tmp3 = get_script_val(cmd+7);
375 if((tmp2 > 255) || (tmp3 > 255))
break;
377 param.
color.g = tmp2;
378 param.
color.b = tmp3;
380 }
else if(strncmp_P(cmd, PSTR(
"GC"), 2) == 0){
382 uint16_t tmp2 = get_script_val(cmd+5);
383 uint16_t tmp3 = get_script_val(cmd+7);
384 if((tmp2 > 255) || (tmp3 > 255))
break;
388 }
else if(strncmp_P(cmd, PSTR(
"PM"), 2) == 0){
401 tmp = get_script_val(ptr);
405 }
else if(strncmp_P(cmd, PSTR(
"WT"), 2) == 0){
412 if(strncmp_P(cmd, PSTR(
"LV"), 2) == 0){
414 uint8_t n = get_script_digit(cmd+2);
417 if((cmd[3] ==
'=') || (cmd[3] ==
'>') || (cmd[3] ==
'<') || (cmd[3] ==
'!')){
418 tmp = get_script_val(cmd+4);
421 case '=':
if(param.
var[n] == tmp)
goto do_loop_cmd;
423 case '>':
if(param.
var[n] > tmp)
goto do_loop_cmd;
425 case '<':
if(param.
var[n] < tmp)
goto do_loop_cmd;
427 case '!':
if(param.
var[n] != tmp)
goto do_loop_cmd;
433 if(param.
var[n] != 0){
438 status = script_seek(&script, popstack());
451 if(strncmp_P(cmd, PSTR(
"END"), 3) == 0){
456 }
else if(strncmp_P(cmd, PSTR(
"CLR"), 3) == 0){
462 }
else if(strncmp_P(cmd, PSTR(
"INF"), 3) == 0){
469 }
else if(strncmp_P(cmd, PSTR(
"RST"), 3) == 0){
471 status = script_seek(&script, 0);
474 }
else if(strncmp_P(cmd, PSTR(
"RPT"), 3) == 0){
477 uint32_t next = script.
pos - (script.
readed - (cmd - buf + 3));
481 }
else if(strncmp_P(cmd, PSTR(
"PNT"), 3) == 0){
484 }
else if(strncmp_P(cmd, PSTR(
"REV"), 3) == 0){
488 }
else if(strncmp_P(cmd, PSTR(
"NEG"), 3) == 0){
501 static void _start(
void){
517 status = sdcard_open();
520 total_script_files = get_script_count();
522 if(total_script_files > 0){
524 status = script_open(&script, script_id);
535 static char* skip_cmd(
char *s){
538 while(s[n] && (s[n] !=
' ') && (s[n] !=
'\n') && (s[n] !=
'\r') && (s[n] !=
'\t')) n++;
548 static char* get_cmd(
char *s){
551 while(s[n] && ((s[n] ==
' ') || (s[n] ==
'\n') || (s[n] ==
'\r') || (s[n] ==
'\t'))) n++;
552 return s[n] ? s + n : NULL;
570 if(script.cmd == NULL){
572 status = script_read_str(&script, buf);
574 script.cmd = get_cmd(buf);
578 result = execute_cmd(script.cmd);
580 script.cmd = get_cmd(skip_cmd(script.cmd));
582 if(result)
return result;
599 #define IND_SD_STATUS 50 608 if(select_next != 0){
643 if(select_next == 0){
648 if(total_script_files){
651 script_id = total_script_files-1;
655 script_id += select_next;
656 if(script_id >= total_script_files) script_id = 0;
659 status = script_open(&script, script_id);
672 static void _stop(
void){
678 #define ANIMATE_DELAY 50 679 #define ANIMATE_LEN 3 686 static effect_info_t _info(uint8_t show){
687 static uint8_t ind_pos;
703 for(uint8_t i=0; i<ANIMATE_LEN; i++){
704 str[i] = i == ind_pos ?
'>' :
'-';
708 if(++ind_pos >= ANIMATE_LEN) ind_pos = 0;
710 str[ANIMATE_LEN] =
' ';
711 str[ANIMATE_LEN+1] = 0;
744 DDR(WS_LOCK_PORT) |= WS_LOCK_PIN;
в скрипте есть бесконечный цикл
uint32_t loop_stack[STACK_DEPTH]
стек циклов
структура параметров скрипта
uint16_t readed
считанное в последний раз кол-во байтов
#define ANIMATE_DELAY
период анимации при воспроизведении скрипта в интервалах по 10 мс
#define SD_BUF_SZ
КОНСТАНТА - размер блока чтения с карты. Может быть МЕНЬШЕ, но НЕ БОЛЬШЕ 256.
uint8_t b
синяя составляющая цвета
void off_all_pixels(void)
Выключение всех пикселов
int8_t delta
условная скорость автоматического изменения яркости
Вспомогательные эффекты ЖКИ
uint32_t pos
следующая позиция в файле для чтения
void set_rgb_color(uint8_t pos, uint8_t r, uint8_t g, uint8_t b)
Пиксел произвольного цвета
uint8_t stack_head
"голова" стека циклов
const __flash effect_t flash_effect_t
тип описания эффекта, размещенного во FLASH.
структура параметров звукового сигнала
#define VAR_CNT
КОНСТАНТА - количество переменных в скрипте, НЕ МЕНЯТЬ
uint8_t var[VAR_CNT]
переменные
Структура, описывающая один пиксель
сервисный модуль для реализации эффектов Набор вспомогательных функций для базовых манипуляций над це...
char filename[13]
имя файла скрипта
void show_rpad_str(uint8_t line, char *src)
вывод строки с очисткой дисплея справа
void center_str_p(uint8_t row, const char *src)
вывод строки из flash по центру дисплея
#define STACK_DEPTH
глубина вложенности циклов в скрипте
Аппаратно-зависимые определения
файл скрипта не найден на карте
#define BACKGROUND_EFFECT
фоновый эффект
preset_result_t
результат функции смены пресета
#define PIXEL_CNT
Общее количество пикселов
Описания модуля скрипт-плейера
#define IND_SD_STATUS
длительность индикации состояния модуля в интервалах по 10 мс
Тип для представления цвета в RGB-модели
script_result_t
тип текущего состояния модуля
Интерфейс визуальных эффектов
uint8_t g
зеленая составляющая цвета
uint8_t r
красная составляющая цвета
pixel_t pixels[MAX_TOTAL_PIX]
Массив пикселей предельного размера
void register_effect(uint8_t toe, flash_effect_t *eff)
Регистрация эффекта в списках
uint8_t bright
яркость пиксела
void * get_reserved_memory(uint16_t *size)
запрос резервной памяти
uint8_t script_execute(char *buf)