Subversion Repositories HomeAutomation

Rev

Rev 349 | Rev 448 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

/**
 * CanSimpleCLCD. Simple version.
 * For HD44780- and KS0073-based LCD displays
 *
 * Contains no intelligence. It just prints what it is told to.
 *
 * @date    2006-12-11
 * @author  Erik Larsson
 *
 */

/*-----------------------------------------------------------------------------
 * Includes
 *---------------------------------------------------------------------------*/
/* system files */
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
/* lib files */
#include <bios.h>
#include <lcd_HD44780.h>
/* funcdefs */
#include <funcdefs.h>

/*-----------------------------------------------------------------------------
 * Defines
 *---------------------------------------------------------------------------*/
#define SIZE_X  20
#define SIZE_Y  4
#define SIZE_LCD LCD_SIZE_20x4

#define BUFFER_SIZE SIZE_X
#define TRUE 1
#define FALSE 0

#define LEFT    0x01
#define RIGHT   0x02

Can_Message_t txMsg;

char incoming_text[ BUFFER_SIZE ];
uint8_t msg_received = FALSE;

uint8_t rot_lastdir = 0,
        rot_laststate = 0;

char buffer[ BUFFER_SIZE ];

void send_dimensions();

void can_receive(Can_Message_t *msg){
    uint32_t act;
    uint8_t m, act_type, lcd_action, lcd_size;
    if( ((msg->Id & CLASS_MASK)>> CLASS_MASK_BITS) == CLASS_ACT ){
        act = (msg->Id & TYPE_MASK) >> TYPE_MASK_BITS;
        act_type = (act & ACT_TYPE_MASK) >> ACT_TYPE_BITS;
        lcd_action = (act & LCD_ACTION_MASK) >> LCD_ACTION_BITS;
        lcd_size = (act & LCD_SIZE_MASK) >> LCD_SIZE_BITS;
    }

    if( act_type == ACT_TYPE_LCD && (lcd_size == SIZE_LCD || lcd_size == LCD_SIZE_ALL)){
        switch( lcd_action ){
            case LCD_ACTION_CLR:
                    // Clear LCD
                    lcd_clrscr();
                break;
            case LCD_ACTION_CURS:
                    // Move cursor
                    lcd_gotoxy( msg->Data.bytes[0],msg->Data.bytes[1] );
                break;
            case LCD_ACTION_GET_SIZE:
                    // Request LCD dimension
                    send_dimensions();
                break;
            case LCD_ACTION_TEXT:
                // Print text to LCD
                for(m=0;m<msg->DataLength;m++){
                    lcd_putc( (char)msg->Data.bytes[m] );
                }
                break;
            case LCD_ACTION_SET_CONT:
                // Set contrast
                if(msg->DataLength == 1){
                    OCR0B = msg->Data.bytes[0];
                }
                break;
            case LCD_ACTION_SET_BLIGHT:
                // Set backlight
                if(msg->DataLength == 1){
                    OCR1AL = msg->Data.bytes[0];
                }
                break;
            case LCD_ACTION_GET_CONT:
                // Get contrast
                txMsg.DataLength = 1;
                txMsg.Id = ( CLASS_ACT<<CLASS_MASK_BITS )|( ACT_TYPE_LCD<<ACT_TYPE_BITS )|( LCD_ACTION_SEND_CONT<<LCD_ACTION_BITS )|NODE_ID;
                txMsg.Data.bytes[0] = OCR0B;
                bios->can_send(&txMsg);
                break;
            case LCD_ACTION_GET_BLIGHT:
                // Get backlight
                txMsg.DataLength = 1;
                txMsg.Id = ( CLASS_ACT<<CLASS_MASK_BITS )|( ACT_TYPE_LCD<<ACT_TYPE_BITS )|( LCD_ACTION_SEND_BLIGHT<<LCD_ACTION_BITS )|NODE_ID;
                txMsg.Data.bytes[0] = OCR1AL;
                bios->can_send(&txMsg);
                break;
            default:
                // Take over the world
                break;
        }
    }
}

ISR( PCINT0_vect ){ // For ROTENC_A and ROTENC_B
    uint8_t rot_data = 0;

    txMsg.Id = ( CLASS_SNS<<CLASS_MASK_BITS )|( SNS_ACT_BUTTON<<SNS_TYPE_BITS )|( 0x01<<SNS_ID_BITS )| NODE_ID;
    txMsg.DataLength=2;

    if(PINB&(1<<PB7)){
        rot_data |= 0x01;
    }
    if(PINB&(1<<PB0)){
        rot_data |= 0x02;
    }

    if( rot_data==0 || rot_data==3 ){
        if( rot_data==0 && rot_laststate!=rot_data ){
            if( rot_lastdir&0x01 ){
                // Moving right
                txMsg.Data.bytes[0]=RIGHT;
                txMsg.Data.bytes[1] = (PIND&(1<<PD2))?0:1;
                bios->can_send(&txMsg);
                // For testing TODO remove
                if(OCR1A<0xFF){
                    OCR1A++;
                }
            }else{
                // Moving left
                txMsg.Data.bytes[0]=LEFT;
                txMsg.Data.bytes[1] = (PIND&(1<<PD2))?0:1;
                bios->can_send(&txMsg);
                // For testing TODO remove
                if(OCR1A>0){
                    OCR1A--;
                }
            }
        }
        rot_laststate = rot_data;
    }else{
        rot_lastdir = rot_data;
    }
}

ISR( PCINT2_vect ){ // For ROTENC_BTN
    txMsg.Id = ( CLASS_SNS<<CLASS_MASK_BITS )|( SNS_ACT_BUTTON<<SNS_TYPE_BITS )|( 0x02<<SNS_ID_BITS )| NODE_ID;
    txMsg.Data.bytes[0] = (PIND&(1<<PD2))?0:1; // Check if buton is pressed or not
    txMsg.DataLength=1;
    bios->can_send(&txMsg);
}

/*-----------------------------------------------------------------------------
 * Main Program
 *---------------------------------------------------------------------------*/
int main(void) {

    /*
     * Initialize rotaryencoders and buttons
     */
    /* Set as input */
    DDRD &= ~(1<<DDD2);
    DDRB &= ~((1<<DDB7)|(1<<DDB0));
    /* Enable pull-up */
    PORTD |= (1<<PD2);
    PORTB |= (1<<PB7)|(1<<PB0);
    /* Enable IO-pin interrupt */
    PCICR |= (1<<PCIE2)|(1<<PCIE0);
    /* Unmask PB7, PB0 and PD2 */
    PCMSK2 |= (1<<PCINT18);
    PCMSK0 |= (1<<PCINT7)|(1<<PCINT0);

    /* Contrast */
    TCCR0A |= (1<<COM0B1)|(1<<WGM01)|(1<<WGM00);
    TCCR0B |= (1<<CS00);
    OCR0B = 0x20;
    DDRD |= (1<<DDD5);

    /* Backlight */
    TCCR1A |= (1<<COM1A1)|(1<<WGM11);
    TCCR1B |= (1<<WGM13)|(1<<WGM12)|(1<<CS10);
    ICR1 = 0xFF; // Make it 8 bits
    OCR1A = 0x20;
    DDRB |= (1<<DDB1);

    txMsg.ExtendedFlag=1;
    txMsg.RemoteFlag=0;

    sei();
    bios->can_callback = &can_receive;

    lcd_init( LCD_DISP_ON );
    lcd_clrscr();
    lcd_puts("HomeAutomation\n");

    send_dimensions();
    lcd_puts("Very nice!\n");

    /* main loop */
    while(1){
        /* check if any messages have been received */
        if(msg_received){

            msg_received = FALSE;
        }
    }
}

void send_dimensions(){
    txMsg.Id=0xA000001;
    txMsg.Data.bytes[0] = SIZE_X;
    txMsg.Data.bytes[1] = SIZE_Y;
    txMsg.DataLength = 2;
    bios->can_send(&txMsg);
}