00001
00299 #include <avr/io.h>
00300 #include <avr/interrupt.h>
00301 #include <avr/wdt.h>
00302 #include <util/delay.h>
00303 #include <avr/pgmspace.h>
00304
00305 #include "usiTwiSlave.h"
00306
00307 #define TWI_SLA 0x10
00309 #define CHANNEL_COUNT 13
00310 #define PORT_COUNT 2
00312 #define OUTPORT0 PORTB
00313 #define OUTDDR0 DDRB
00314 #define OUTMASK0 0x5F
00316 #define OUTPORT1 PORTD
00317 #define OUTDDR1 DDRD
00318 #define OUTMASK1 0x7F
00326 const uint8_t channel_port[CHANNEL_COUNT] PROGMEM = {
00327 0, 0, 0, 0, 0, 0,
00328 1, 1, 1, 1, 1, 1, 1 };
00330 const uint8_t channel_pin[CHANNEL_COUNT] PROGMEM = {
00331 0x01, 0x02, 0x04, 0x08, 0x10, 0x40,
00332 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40 };
00333
00334
00335
00336
00337
00338
00339
00340 #define STATE_COUNT 14
00341 #define STATE_START_COUNT 2
00343 const uint16_t switch_timer[STATE_COUNT] PROGMEM = {
00344 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 4096 };
00346 const uint8_t switch_timer_index[STATE_START_COUNT]= { 13, 0 };
00347
00349 uint8_t switch_state[STATE_COUNT][PORT_COUNT];
00350
00351 uint8_t switch_state_new[STATE_COUNT][PORT_COUNT];
00356 typedef enum {
00357 WAIT_FOR_ADDRESS,
00358 WAIT_FOR_VALUE_LOW,
00359 WAIT_FOR_VALUE_HIGH,
00360 } ReadCommandState;
00361
00367 typedef struct {
00368 uint8_t address;
00370 uint16_t value;
00372 ReadCommandState state;
00373 } Command;
00374
00376 Command command = {0, 0, WAIT_FOR_ADDRESS};
00377
00381 void timer_start() {
00382 TCCR1A = 0x00;
00383
00384
00385
00386 TCCR1B = (0 << WGM13) | (0 << WGM12) | (0 << CS12) | (1 << CS11) | (0 << CS10);
00387 sei();
00388 }
00389
00395 void set_brightness(uint8_t channel, uint16_t brightness){
00396 uint8_t i;
00397
00398 uint8_t mask= pgm_read_word(&channel_pin[channel]);
00399 uint8_t port= pgm_read_word(&channel_port[channel]);
00400
00401 for (i= 0; i < STATE_COUNT; i++){
00402
00403 if (brightness & 1) {
00404
00405 switch_state_new[i][port] |= mask;
00406 } else {
00407
00408 switch_state_new[i][port] &= ~mask;
00409 }
00410
00411 brightness >>= 1;
00412 }
00413 }
00414
00418 void init_ports(void){
00419 OUTDDR0 |= OUTMASK0;
00420 OUTPORT0 &= ~OUTMASK0;
00421
00422 OUTDDR1 |= OUTMASK1;
00423 OUTPORT1 &= ~OUTMASK1;
00424 }
00425
00431 void set_port(int port, uint8_t state){
00432 switch(port){
00433 case 0:
00434 OUTPORT0 |= (state & OUTMASK0);
00435 OUTPORT0 &= (state | ~OUTMASK0);
00436 break;
00437 case 1:
00438 OUTPORT1 |= (state & OUTMASK1);
00439 OUTPORT1 &= (state | ~OUTMASK1);
00440 break;
00441 }
00442 }
00443
00449 void evaluate_i2c_input(void) {
00450 uint8_t byte_received = 0;
00451 if (usiTwiDataInReceiveBuffer()) {
00452
00453 byte_received = usiTwiReceiveByte();
00454 switch(command.state){
00455 case WAIT_FOR_ADDRESS:
00456 if (byte_received & 0x80) {
00457
00458 command.address = (byte_received & 0x7f);
00459 command.state = WAIT_FOR_VALUE_LOW;
00460 }
00461
00462 break;
00463 case WAIT_FOR_VALUE_LOW:
00464 if (!(byte_received & 0x80)) {
00465
00466 command.value = byte_received;
00467 command.state = WAIT_FOR_VALUE_HIGH;
00468 } else {
00469
00470 command.address = byte_received;
00471 command.state = WAIT_FOR_VALUE_LOW;
00472 }
00473 break;
00474 case WAIT_FOR_VALUE_HIGH:
00475 if (!(byte_received & 0x80)) {
00476
00477 command.value += (byte_received << 7);
00478 command.state = WAIT_FOR_ADDRESS;
00479
00480 set_brightness(command.address, command.value);
00481 } else {
00482
00483 command.address = byte_received;
00484 command.state = WAIT_FOR_VALUE_LOW;
00485 }
00486 break;
00487 }
00488 }
00489 }
00490
00496 int main(void) {
00497 uint8_t state_number = 0;
00498 uint8_t state_start = 0;
00499 uint8_t port = 0;
00500 uint16_t timer = 0;
00501
00502
00503 init_ports();
00504
00505 uint8_t i;
00506 for(i= 0; i < CHANNEL_COUNT; i++) {
00507 set_brightness(i, 0);
00508 }
00509
00510
00511 usiTwiSlaveInit(TWI_SLA);
00512
00513
00514 timer_start();
00515
00516
00517 wdt_enable(WDTO_15MS);
00518
00519 while (1) {
00520
00521 for (state_start = 0; state_start < STATE_START_COUNT; state_start++) {
00522
00523 for (state_number = switch_timer_index[state_start]; state_number < STATE_COUNT; state_number++) {
00524
00525 for (port = 0; port < PORT_COUNT; port++) {
00526
00527 set_port(port, switch_state[state_number][port]);
00528 }
00529
00530 timer = pgm_read_word(&switch_timer[state_number]);
00531
00532 TCNT1 = 0;
00533 while (timer > TCNT1) {
00534
00535 wdt_reset();
00536 evaluate_i2c_input();
00537 }
00538 }
00539 }
00540 for(state_number= 0; state_number < STATE_COUNT; state_number++) {
00541 for(port= 0; port < PORT_COUNT; port++) {
00542 switch_state[state_number][port]=
00543 switch_state_new[state_number][port];
00544 }
00545 }
00546 }
00547 return 0;
00548 }