Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[moved] SIRC Decoder using LCD

Status
Not open for further replies.

denny9167

Junior Member level 2
Joined
Apr 23, 2022
Messages
20
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
126
I thought I would share My SIRC decoder for anyone interested. I use it to test my IR remotes for my motorized volume controls.

Code:
/*
 * File:   sirc887.c
 * Author: Denny Brown
 *
 * Created on March 23, 2022, 2:18 PM
 */

// Sony Remote 40kHz 7 bits command (LSB first) then 5 bits address
// there are also 15 bit and 20 bit versions of Sony protocol
//
// 40kHz 7 bits command (LSB first) then 5 bits address
// 2.4ms mark=start
// 0.6sp, 0.6 mark = 0
// 0.6sp, 1.2 mark = 1
//
// tv               address=01
// vcr1             address=02
// vcr2             address=03
// radio/cd         address=04
// laser disc       address=06
// surround sound   address=0c
// tuner            address=0d
// amp              address=10 (theatre / cassette / tuner)
// cd player        address=11
// equaliser        address=12
// HDMI control     address=17
// dvd              address=1a

//PIC16F887 Configuration bits settings

// Device:  PIC16F887

// BEGIN CONFIG
#pragma config FOSC = INTRC_NOCLKOUT
#pragma config WDTE = OFF
#pragma config PWRTE = OFF 
#pragma config BOREN = ON
#pragma config LVP = OFF 
#pragma config CPD = OFF
#pragma config WRT = OFF 
#pragma config CP = OFF 
//END CONFIG




#include <xc.h>
#include <stdint.h>
#include <stdio.h>


#define _XTAL_FREQ 8000000


//LCD function defines

#define LCD_FIRST_ROW          0x80
#define LCD_SECOND_ROW         0xC0
#define LCD_THIRD_ROW          0x94
#define LCD_FOURTH_ROW         0xD4
#define LCD_CLEAR              0x01
#define LCD_RETURN_HOME        0x02
#define LCD_ENTRY_MODE_SET     0x04
#define LCD_CURSOR_OFF         0x0C
#define LCD_UNDERLINE_ON       0x0E
#define LCD_BLINK_CURSOR_ON    0x0F
#define LCD_MOVE_CURSOR_LEFT   0x10
#define LCD_MOVE_CURSOR_RIGHT  0x14
#define LCD_TURN_ON            0x0C
#define LCD_TURN_OFF           0x08
#define LCD_SHIFT_LEFT         0x18
#define LCD_SHIFT_RIGHT        0x1E

#ifndef LCD_TYPE
   #define LCD_TYPE 2           // 0=5x7, 1=5x10, 2=2 lines
#endif


#define IR_RX        PORTBbits.RB0                  // IR receiver 40KHz


//LCD module connections
#define LCD_RS       PORTDbits.RD2
#define LCD_EN       PORTDbits.RD3
#define LCD_D4       PORTDbits.RD4
#define LCD_D5       PORTDbits.RD5
#define LCD_D6       PORTDbits.RD6
#define LCD_D7       PORTDbits.RD7
#define LCD_RS_DIR   TRISDbits.TRISD2
#define LCD_EN_DIR   TRISDbits.TRISD3
#define LCD_D4_DIR   TRISDbits.TRISD4
#define LCD_D5_DIR   TRISDbits.TRISD5
#define LCD_D6_DIR   TRISDbits.TRISD6
#define LCD_D7_DIR   TRISDbits.TRISD7
//End LCD module connections


//LCD firmware

 __bit RS;

void LCD_Write_Nibble(uint8_t n)
   
{
  LCD_RS = RS;
  LCD_D4 = n & 0x01;
  LCD_D5 = (n >> 1) & 0x01;
  LCD_D6 = (n >> 2) & 0x01;
  LCD_D7 = (n >> 3) & 0x01;

  // send enable pulse
  LCD_EN = 0;
  __delay_us(1);
  LCD_EN = 1;
  __delay_us(1);
  LCD_EN = 0;
  __delay_us(100);
}

void LCD_Cmd(uint8_t Command)
{
  RS = 0;
  LCD_Write_Nibble(Command >> 4);
  LCD_Write_Nibble(Command);
  if((Command == LCD_CLEAR) || (Command == LCD_RETURN_HOME))
    __delay_ms(2);
}

void LCD_Set_Cursor(uint8_t col, uint8_t row)
{
  switch(row)
  {
    case 2:
      LCD_Cmd(LCD_SECOND_ROW + col - 1);
      break;
    case 3:
      LCD_Cmd(LCD_THIRD_ROW  + col - 1);
      break;
    case 4:
      LCD_Cmd(LCD_FOURTH_ROW + col - 1);
    break;
    default:      // case 1:
      LCD_Cmd(LCD_FIRST_ROW  + col - 1);
  }

}



void LCD_Write_String(const char* LCD_Str)
{
  uint8_t i = 0;
  RS = 1;
  while(LCD_Str[i] != '\0')
  {
    LCD_Write_Nibble(LCD_Str[i] >> 4);
    LCD_Write_Nibble(LCD_Str[i++] );
  }
}

void LCD_Begin()
{
  RS = 0;

  LCD_RS     = 0;
  LCD_EN     = 0;
  LCD_D4     = 0;
  LCD_D5     = 0;
  LCD_D6     = 0;
  LCD_D7     = 0;
  LCD_RS_DIR = 0;
  LCD_EN_DIR = 0;
  LCD_D4_DIR = 0;
  LCD_D5_DIR = 0;
  LCD_D6_DIR = 0;
  LCD_D7_DIR = 0;

  __delay_ms(40);
  LCD_Cmd(3);
  __delay_ms(5);
  LCD_Cmd(3);
  __delay_ms(5);
  LCD_Cmd(3);
  __delay_ms(5);
  LCD_Cmd(LCD_RETURN_HOME);
  __delay_ms(5);
  LCD_Cmd(0x20 | (LCD_TYPE << 2));
  __delay_ms(50);
  LCD_Cmd(LCD_TURN_ON);
  __delay_ms(50);
  LCD_Cmd(LCD_CLEAR);
  __delay_ms(50);
  LCD_Cmd(LCD_ENTRY_MODE_SET | LCD_RETURN_HOME);
  __delay_ms(50);

// function prototypes
void get_mark_time(void);               // get Sony IR mark time

// global variables
unsigned char counter = 0;
unsigned char bitcount;
unsigned char ir_address;
unsigned char ir_command;
unsigned int mark_time;

void __interrupt() ISR(void){

    if (INTCON.T0IF) {
        counter++;                    // increment counter
        INTCON.T0IF = 0;                 // Clear Timer0 overflow interrupt flag
    }
}


/*************************** main function *********************/
void main(void)
{
  OSCCON = 0x70;   // set internal oscillator to 8MHz
  ANSELH = 0;      // configure all PORTB pins as digital
  TRISD  = 0x00;
  OPTION_REG = 0x84;            // TMR0 prescaler set to 1:32, pull-ups enable
  
  INTCON = 0xC8;  // enable global, peripheral and PORTB change interrupts
  

  
    // start timer 0 counting
    INTCON.GIE = 1;               // Global interrupt enable
    INTCON.T0IE = 1;              // Enable Timer0 overflow interrupt



  __delay_ms(1000);   // wait 1 second

  LCD_Begin();       // initialize LCD module
  LCD_Set_Cursor(3, 1);
  LCD_Write_String("SIRC Protocol");
  LCD_Set_Cursor(5, 2);
  LCD_Write_String("Decoder");
  __delay_ms(4000);  //wait 2 seconds
  LCD_Cmd(LCD_CLEAR);
  LCD_Set_Cursor(3, 1);
  LCD_Write_String("Brown Audio");
  LCD_Set_Cursor(5, 2);    // move cursor to column 1, row 2
  LCD_Write_String("  Labs  ");
  __delay_ms(4000);
  LCD_Cmd(LCD_CLEAR);
  LCD_Set_Cursor(1, 1);    // move cursor to column 1, row 1
  LCD_Write_String("Command:0x00");
  LCD_Set_Cursor(1, 2);    // move cursor to column 1, row 2
  LCD_Write_String("Address:0x00");


while(1)
  {
    ir_command = 0;                     // initialise to prevent false trigger
    ir_address = 0;                     // initialise to prevent false trigger
    get_mark_time();                     // get Sony leader - 2.4mS Mark, 1.2mS space
    if ((mark_time > 0x80) && (mark_time < 0xB0)){         // ignore anything but 2.4mS mark
        
    for(bitcount = 0 ; bitcount < 7 ; bitcount++){    // 7 bit command
    get_mark_time();                               // get a Sony IR bit
    ir_command >>= 1;                              // shift
    ir_command &= 0x7f;                            // top bit zero
    if (mark_time > 0x40){                         // > 40 is assumed to be a 1
    ir_command ^= 0x80;                        // top bit 1
                }
            }
    ir_command >>= 1;                                  // shift 1 unused bit
    ir_command &= 0x7F;                                // clear top bit

    for(bitcount = 0 ; bitcount < 5 ; bitcount++){     // 5 bit address
    get_mark_time();                               // get a Sony IR bit
    ir_address >>= 1;                              // shift
    ir_address &= 0x7f;                            // top bit zero
    if (mark_time > 0x40){
    ir_address ^= 0x80;                        // top bit 1
                }
            }
    ir_address >>= 3;                                  // shift 3 unused bits
    ir_address &= 0x1F;                                // clear top 3 bits

        }

    sprintf(text,"%02X",ir_command);
    LCD_Set_Cursor(11, 1);   // move cursor to column 11 line 1
    LCD_Write_String(text);   // print address

    sprintf(text,"%02X",ir_address);
    LCD_Set_Cursor(11, 2);    // move cursor to column 7 line 2
    LCD_Write_String(text);   // print command

    }

}

// get time of mark, then ignore space
void get_mark_time(void){
    while(IR_RX);                           // wait for a mark
    counter=0;
    TMR0 = 0;
    while(!IR_RX);                          // wait for space
    mark_time = (counter << 8) + TMR0;      // collect integer mark time

}
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top