/** main function */ int main(void) { init_output(); init_pwm(); #if SERIAL_UART init_uart(); #endif #if RC5_DECODER init_rc5(); #endif #if I2C init_i2c(); #endif global_pwm.channels[0].brightness = 50; global_pwm.channels[0].target_brightness = 50; #if STATIC_SCRIPTS init_script_threads(); #if RS485_CTRL == 0 /* start the example scripts */ script_threads[0].handler.execute = &memory_handler_flash; script_threads[0].handler.position = (uint16_t) &colorchange_red; script_threads[0].flags.disabled = 0; //script_threads[1].handler.execute = &memory_handler_flash; //script_threads[1].handler.position = (uint16_t) &testscript_flash2; //script_threads[1].flags.disabled = 0; // //script_threads[2].handler.execute = &memory_handler_eeprom; //script_threads[2].handler.position = (uint16_t) &testscript_eeprom; //script_threads[2].flags.disabled = 0; //script_threads[0].handler.execute = &memory_handler_flash; //script_threads[0].handler.position = (uint16_t) &blinken; //script_threads[0].flags.disabled = 0; #endif #endif #if I2C_MASTER i2c_global.send_messages[0].command.size = 4; i2c_global.send_messages[0].command.code = COMMAND_SET_COLOR; i2c_global.send_messages[0].command.set_color_parameters.colors[0] = 0x10; i2c_global.send_messages[0].command.set_color_parameters.colors[1] = 0x10; i2c_global.send_messages[0].command.set_color_parameters.colors[2] = 0x10; i2c_global.send_messages_count = 1; #endif #if RS485_CTRL /* init command bus */ UCSR0A = _BV(MPCM0); /* enable multi-processor communication mode */ UCSR0C = _BV(UCSZ00) | _BV(UCSZ01); /* 9 bit frame size */ #define UART_UBRR 8 /* 115200 baud at 16mhz */ UBRR0H = HIGH(UART_UBRR); UBRR0L = LOW(UART_UBRR); UCSR0B = _BV(RXEN0) | _BV(TXEN0) | _BV(UCSZ02); /* enable receiver and transmitter */ #endif /* enable interrupts globally */ sei(); while (1) { /* after the last pwm timeslot, rebuild the timeslot table */ if (global.flags.last_pulse) { global.flags.last_pulse = 0; update_pwm_timeslots(); } /* at the beginning of each pwm cycle, call the fading engine and * execute all script threads */ if (global.flags.new_cycle) { global.flags.new_cycle = 0; update_brightness(); #if STATIC_SCRIPTS execute_script_threads(); #endif continue; } #if SERIAL_UART /* check if we received something via uart */ if (fifo_fill(&global_uart.rx_fifo) > 0) { check_serial_input(fifo_load(&global_uart.rx_fifo)); continue; } #endif #if RC5_DECODER /* check if we received something via ir */ if (global_rc5.new_data) { static uint8_t toggle_bit = 2; /* if key has been pressed again */ if (global_rc5.received_command.toggle_bit != toggle_bit) { /* if code is 0x01 (key '1' on a default remote) */ if (global_rc5.received_command.code == 0x01) { /* install script into thread 1 */ script_threads[1].handler.execute = &memory_handler_flash; script_threads[1].handler.position = (uint16_t) &green_flash; script_threads[1].flags.disabled = 0; script_threads[1].handler_stack_offset = 0; } /* store new toggle bit state */ toggle_bit = global_rc5.received_command.toggle_bit; } /* reset the new_data flag, so that new commands can be received */ global_rc5.new_data = 0; continue; } #endif #if RS485_CTRL if (UCSR0A & _BV(RXC0)) { uint8_t address = UCSR0B & _BV(RXB80); /* read nineth bit, zero if data, one if address */ uint8_t data = UDR0; static uint8_t buffer[8]; static uint8_t fill = 0; if (UCSR0A & _BV(MPCM0) || address) { /* if MPCM mode is still active, or ninth bit set, this is an address packet */ /* check if we are ment */ if (data == 0 || data == RS485_ADDRESS) { /* remove MPCM flag and reset buffer fill counter */ UCSR0A &= ~_BV(MPCM0); fill = 0; continue; } else {/* turn on MPCM */ UCSR0A |= _BV(MPCM0); continue; } } /* else this is a data packet, put data into buffer */ buffer[fill++] = data; if (buffer[0] == 0x01) { /* soft reset */ jump_to_bootloader(); } else if (buffer[0] == 0x02 && fill == 4) { /* set color */ for (uint8_t pos = 0; pos < 3; pos++) { global_pwm.channels[pos].target_brightness = buffer[pos + 1]; global_pwm.channels[pos].brightness = buffer[pos + 1]; } UCSR0A |= _BV(MPCM0); /* return to MPCM mode */ } else if (buffer[0] == 0x03 && fill == 6) { /* fade to color */ for (uint8_t pos = 0; pos < 3; pos++) { global_pwm.channels[pos].speed_h = buffer[1]; global_pwm.channels[pos].speed_l = buffer[2]; global_pwm.channels[pos].target_brightness = buffer[pos + 3]; } UCSR0A |= _BV(MPCM0); /* return to MPCM mode */ } } #endif #if I2C_MASTER i2c_master_check_queue(); #endif } }
/** * Reads a single HTTP header line from ctx->input and parses it. * Header continuation is handled transparently. Trailing space characters * are discarded from the header line and the line is NUL-terminated. * * @param ctx an initialized ``http_t'' in state HTTP_STATE_HEADERS. * @param buf a work buffer. * @param buf_size the size of buf; this defines the maximum length of * headers that can be handled. * * @return * -1 if a header was invalid (see http status for details). * 0 if the end-of-headers was reached. * 1 if a header was successfully parsed. */ int http_read_header(http_t *ctx, char *buf, size_t buf_size) { char *p; size_t size; RUNTIME_ASSERT(ctx); RUNTIME_ASSERT(buf); RUNTIME_ASSERT(buf_size > 0); RUNTIME_ASSERT(ctx->state == HTTP_STATE_HEADERS); p = buf; size = buf_size; for (;;) { ssize_t r; r = fifo_findchar(ctx->input, '\n', size); if ((ssize_t) -1 == r) { if ((size_t) fifo_fill(ctx->input) > size) DBUG("Header line is too long"); else DBUG("Header line is not yet terminated"); ctx->keep_alive = false; http_set_status(ctx, 413, "Request Entity Too Large"); return -1; } RUNTIME_ASSERT(r >= 0 && (size_t) r < size); /* Make sure the headers don't contain any NUL characters */ if ((ssize_t) -1 != fifo_findchar(ctx->input, '\0', r)) { ctx->keep_alive = false; http_set_status(ctx, 400, "Bad Request (NUL in Header)"); return -1; } fifo_read(ctx->input, p, 1 + r); RUNTIME_ASSERT('\n' == p[r]); /* Discard trailing '\r' characters */ for (/* NOTHING*/; r > 0; r--) { if ('\r' != p[r - 1]) break; } RUNTIME_ASSERT('\n' == p[r] || '\r' == p[r]); p[r] = '\0'; /* Check for a header continuation with HT (0x09) or a space (0x20) */ if ( 0 != fifo_findchar(ctx->input, 0x09, 1) && 0 != fifo_findchar(ctx->input, 0x20, 1) ) { /* Discard all trailing spaces */ if (isspace((unsigned char) p[r])) { while (r > 0 && isspace((unsigned char) p[r - 1])) r--; p[r] = '\0'; } break; } p += r; size -= r; /* Discard all consecutive HT and SP characters */ fifo_skip_chars(ctx->input, fifo_fill(ctx->input), "\x09\x20"); /* Replace all skipped space by a single space character */ if (size > 0) { *p++ = 0x20; size--; } } if (ctx->debug_dump_headers) { http_log(ctx, "\t%s", buf); } if ('\0' == *buf) { ctx->state = HTTP_STATE_BODY; return 0; } return 1; }