/** 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
    }
}
Example #2
0
/**
 * 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;
}