/**********************************************************************/ /* Morse Engine */ /* Generates Morse Code */ /* */ /* Version: 1.2 */ /* */ /* By: J. Winpenny */ /* */ /* Date: 5th March 2000 */ /* */ /*--------------------------------------------------------------------*/ /* Hardware: PIC16F8xx */ /* Port C bit 2 connected to Beeper */ /* ( 0 = On, 1 = Off ) */ /* */ /* PORT D used for LCD */ /*--------------------------------------------------------------------*/ /* */ /* Function: */ /* */ /* Sends some test Morse Code */ /* and displays the characters on an LCD */ /* */ /* Future plans: */ /* */ /* 1) Add a library using EEPROM, to send random words in Morse */ /* */ /* */ /* */ /* Notes: */ /* Modifications to version 1.1 */ /* Corrected WordDelay */ /* */ /**********************************************************************/ #pragma CLOCK_FREQ 3579545 // Processor clock frequency in Hz. /* LCD Related */ void LCD_WaitBusyFlag(void); void LCD_Setup(void); void LCD_FunctionMode(void); void LCD_DataMode(void); void LCD_Write_8_Bit(char); void LCD_Write_4_Bit(char); void LCD_Delay(void); void LCD_Clear(void); void LCD_SetPos(char); void LCD_Line_1(void); void LCD_Line_2(void); void LCD_NormalMode(void); void LCD_ShiftMode(void); void LCDClearLine1(void); void LCDClearLine2(void); void WriteLCDString( const char *); void WriteLCD( char *lcdptr ); /* Definitions for the LCD interface */ #define LCD_SEL 3 /* Port D bit 3 ( Enables LCD ) */ #define LCD_WR 2 /* Port D bit 2 ( Logic 0 = Write ) */ #define LCD_RS 1 /* Port D bit 1 ( Register select ) */ #define LCD_DATA 0x08 #define BUSY_BIT 7 #define BUSY_MASK 0x80 // PORT D Bits 4,5,6,7 #define LCD_DATA_4 4 /* LCD BIT 0 */ #define LCD_DATA_5 5 /* LCD BIT 1 */ #define LCD_DATA_6 6 /* LCD BIT 2 */ #define LCD_DATA_7 7 /* LCD BIT 3 */ /**********************************************************************/ /* LCD Commands ( Refer to LCD Data Sheet ) */ /* Standard command should work with most common devices */ /**********************************************************************/ #define clear_lcd 0x01 /* Clear Display */ #define return_home 0x02 /* Cursor to Home position */ #define entry_mode 0x06 /* Normal entry mode */ #define entry_mode_shift 0x07 /* - with shift */ #define system_set_8_bit 0x38 /* 8 bit data mode 2 line ( 5x7 font ) */ #define system_set_4_bit 0x28 /* 4 bit data mode 2 line ( 5x7 font ) */ #define display_on 0x0c /* Switch ON Display */ #define display_off 0x08 /* Cursor plus blink */ #define set_dd_line1 0x80 /* Line 1 position 1 */ #define set_dd_line2 0xC0 /* Line 2 position 1 */ #define set_dd_ram 0x80 /* Line 1 position 1 */ #define write_data 0x00 /* With rs = 1 */ #define cursor_on 0x0E /* Switch Cursor ON */ #define cursor_off 0x0C /* Switch Cursor OFF */ /**********************************************************************/ // Port addresses char PORTC@0x07; char PORTD@0x08; char PORTE@0x09; // USART Registers char TXREG@0x19; char RCREG@0x1a; char TXSTA@0x98; char RCSTA@0x18; char SPBRG@0x99; // Extra Ports on PIC16F877 char TRISC@0x87; char TRISD@0x88; char TRISE@0x89; // Other PIC registers char PIE1@0x8c; char PIE2@0x8d; char PIR1@0x0c; char PIR2@0x0d; char PCON@0x8e; // ADC bits char ADCON0@0x1f; char ADCON1@0x9f; // USART Register bits #define CSCR 7 #define TX9 6 #define TXEN 5 #define SYNC 4 #define BRGH 2 #define TRMT 1 #define TX9D 0 #define SPEN 7 #define RX9 6 #define SREN 5 #define CREN 4 #define ADDEN 3 #define FERR 2 #define OERR 1 #define RX9D 0 #define TRMT_MASK 2 // Masks for PIR1 #define PSPIF_MASK 0x80 #define ADIF_MASK 0x40 #define RCIF_MASK 0x20 #define TXIF_MASK 0x10 // Bits of SSPSTAT #define SMP 7 #define CKE 6 #define D_A 5 #define P 4 #define S 3 #define R_W 2 #define R_W_MASK 0x04 #define UA 1 #define BF 0 // Bits of SSPCON2 #define GCEN 7 #define ACKSTAT 6 #define ACKDT 5 #define ACKEN 4 #define RCEN 3 #define PEN 2 #define RSEN 1 #define SEN 0 // PORT Configuration #define PortAConfig 0x00 #define PortBConfig 0xf0 #define PortCConfig 0x98 /* SCL & SDA as Inputs */ #define PortDConfig 0x00 #define PortEConfig 0x00 void Setup(void); void ConfigureComms(void); // Configure the USART void SendMorseChar( char Character ); void DitDah( char DitDahType ); void SendMorseString( char *String ); void MorseDelay( char num ); // Morse code beeper ( 0 = On ) #define Beeper 2; // Port C bit 2 // Morse definitions #define DitPeriod 1 #define DahPeriod 3 #define CharacterDelay 3 #define WordDelay 4 // Total = 7 ( Including Character Delay ) /***********************************************************/ /* Encoding of Numbers & letters EEEEENNN. */ /* Where E = morse bit - ( 1 = dah, 0 = dit ) */ /* NNN = number of bits. */ /***********************************************************/ const char Letters[] = { 0x42,0x84,0xA4,0x83, // A,B,C,D 0x01,0x24,0xC3,0x04, // E,F,G,H 0x02,0x74,0xA3,0x44, // I,J,K,L 0xC2,0x82,0xE3,0x64, // M,N,O,P 0xD4,0x43,0x03,0x81, // Q,R,S,T 0x23,0x14,0x63,0x94, // U,V,W,X 0xB4,0xC4 }; // Y,Z const char Numbers[] = { 0xFD,0x7D,0x3D,0x1D,0x0D,0x05,0x85,0xC5,0xE5,0xF5 }; // 0 - 9 char Speed; // Morse Speed factor; char ModeFlags; char LCD_gp; char *Test1 = "Morse code test"; char *Test2 = "0123456789"; void main(void) { Setup(); LCDClearLine1(); WriteLCDString("Morse Engine"); Speed = 2 * 24; // Send some test Morse while( 1 ) { LCDClearLine2(); SendMorseChar('C'); SendMorseChar('Q'); SendMorseChar('C'); SendMorseChar('Q'); SendMorseChar('D'); SendMorseChar('E'); delay_s(1); LCDClearLine2(); SendMorseString( Test1 ); delay_s(1); LCDClearLine2(); SendMorseString( Test2 ); delay_s(1); } } /*****************************************************/ /* setup PIC16F877 options,ports,interrupts */ /*****************************************************/ void Setup(void) { INTCON = 0x00; set_bit( INTCON, GIE ); // Enable Global Interrupts set_bit( INTCON, PEIE ); // Enable all Peripheral Interrupts OPTION_REG = 0x0E; // Set Option register // Prescaler = WDT // 0x0C = WDT rate := 1:16 // 0x0E = WDT rate := 1:64 TRISD = PortDConfig; ADCON1 = 0x7f; // Disable ADC //PCON = 0x03; // Reset Power up status flags TRISA = PortAConfig; TRISB = PortBConfig; TRISC = PortCConfig; TRISE = PortEConfig; PIR1 = 0; output_high_port_c( Beeper ); // Beeper Off LCD_Setup(); // ConfigureComms(); // Configure USART for Asynchronous Comms // Not used in this implementation. } /*******************************************************/ /* Configure USART for communications */ /* */ /* Asynchronous mode */ /* 19,200 Baud ( With 3.579545 Mhz Clock ) */ /* 8 data bits ( For other rates see PIC16F8XX Data ) */ /* 1 stop bit */ /* No Parity */ /* */ /*******************************************************/ void ConfigureComms(void) { set_bit( RCSTA, SPEN ); // Enable Serial port clear_bit( RCSTA, RX9 ); // 8 bit receive mode clear_bit( TXSTA, TX9 ); // 8 bit transmit mode // Values for a clock frequency of 3.579545Mhz // for other clock frequency values see the microchip data. // SPBRG = 0; // SPBRG = 1 ( Set Baud rate 115,200 ) // SPBRG = 5; // SPBRG = 5 ( Set Baud rate 38,400 ) // SPBRG = 22; // SPBRG = 22 ( Set Baud rate 9,600 ) // SPBRG = 11; // SPBRG = 11 ( Set Baud rate 19,200 ) SPBRG = 22; // SPBRG = 22 ( Set Baud rate 9,600 ) // SPBRG = 185; // SPBRG = 185 with BRGH = 0 = 300 Baud // SPBRG = 46; // SPBRG = 46 with BRGH = 0 = 1200 Baud set_bit( TXSTA, BRGH ); // BRGH = 1 ( High speed mode ) // clear_bit( TXSTA, BRGH ); // BRGH = 0 ( Low speed mode ) clear_bit( TXSTA, SYNC ); // Asynchronous mode; set_bit( TXSTA, TXEN ); // Enable Transmitter set_bit( PIE1, RCIE ); // Enable Receive Interrupt set_bit( RCSTA, CREN ); // Enable continuous receive clear_bit( PIR1, RCIF ); // Clear Receive Interrupt flag set_bit( INTCON, PEIE ); // Enable all Peripheral Interrupts set_bit( INTCON, GIE ); // Enable Global Interrupts } /***********************************/ /* Send the Morse equivalent of */ /* the string */ /***********************************/ void SendMorseString( char *String ) { char i = 0; while( String[i] != 0 ) { LCD_Write_4_Bit(String[i]); // Show the character to be sent next... if ( String[i] == ' ' ) { // Delay Period between words // ( Exclude the Character Delay ) MorseDelay( WordDelay ); } else { SendMorseChar( String[i] ); } i++; } } /***********************************/ /* Send a Morse Character */ /***********************************/ void SendMorseChar( char Character ) { char c; char d; char len; char MorseChar; // Select from the Letters / Numbers lookup table. if ( (( Character >= 'A' )&&(Character <= 'Z' ))|| (( Character >= 'a' )&&(Character <= 'z' )) ) { d = Character | 0x20; // Convert to lower case d = d - 'a'; MorseChar = Letters[d]; // Letters } else if( (Character >= '0')&&(Character <= '9')) { d = Character - '0'; MorseChar = Numbers[d]; // Numbers } else { WriteLCDString("Punctuation ?"); return; } len = MorseChar & 0x07; // Get the number of dit/dah's d = 0x80; // Mask for selection of character element. // Select the element in the character // and do a Dit or Dah as necessary. for( c = 0; c < len; c++ ) { if ( ( MorseChar & d ) == 0 ) { DitDah( DitPeriod ); // It's a dit } else { DitDah( DahPeriod ); // It's a Dah } d >>= 1; MorseDelay( DitPeriod ); // Inter - element delay } MorseDelay( CharacterDelay ); // Inter-Character delay. } /***********************************/ /* Sound Beeper for a dit or Dah */ /***********************************/ void DitDah( char DitDahType ) { int c; output_low_port_c( Beeper ); // Beeper On for( c = 0; c < ( Speed * DitDahType ); c++ ) { delay_ms(1); // Could create a rough tone here. // by toggling an output bit... } output_high_port_c( Beeper ); // Beeper Off } /******************************/ /* Selectable delay routine */ /******************************/ void MorseDelay( char num ) { int c; for ( c=0; c < (Speed * num); c++ ) { delay_ms( 1 ); } } /***************************************************************************/ /* Lcd.c LCD interface routines */ /* Version : 2.1. for PIC16xxxx */ /* */ /* J. Winpenny 2/3/2000 */ /* */ /* */ /* Mode : HD44780 type LCD */ /* */ /* */ /* Notes : */ /* */ /***************************************************************************/ //#define speed20 #define speed4 /***********************************/ /* Setup the lcd device */ /***********************************/ void LCD_Setup(void) { /* Reset the LCD */ clear_bit( ModeFlags, 0 ); /* Default to Function Mode */ LCD_Write_8_Bit( system_set_4_bit ); /* This sequence resets the LCD */ LCD_Write_8_Bit( system_set_4_bit ); LCD_Write_8_Bit( system_set_4_bit ); LCD_Write_4_Bit( system_set_4_bit ); LCD_WaitBusyFlag(); LCD_Write_4_Bit( display_on ); LCD_Write_4_Bit( clear_lcd ); LCD_Write_4_Bit( entry_mode ); LCD_Write_4_Bit( set_dd_ram ); set_bit( ModeFlags, 0 ); /* Data Mode */ } /***********************************/ /* Test LCD Busy flag */ /***********************************/ void LCD_WaitBusyFlag(void) { set_bit( STATUS, RP0 ); // Register Page 1 TRISD = ( PortDConfig | 0xf0 ); // Make LCD port input clear_bit( STATUS, RP0 ); // Register page 0 set_bit( PORTD, LCD_WR ); // Read mode set_bit( PORTD, LCD_SEL); // Select LCD // Wait for LCD to respond while( ( PORTD & BUSY_MASK ) != 0 ) { nop(); } clear_bit( PORTD, LCD_SEL ); // de-select LCD clear_bit( PORTD, LCD_WR ); // Write mode // Reset Port D 4,7 to Output set_bit( STATUS, RP0 ); // Register Page 1 TRISD = PortDConfig; clear_bit( STATUS, RP0 ); // Register page 0 } /***********************************/ /* Put LCD in Function Mode */ /***********************************/ void LCD_FunctionMode(void) { clear_bit( ModeFlags, 0 ); /* Save Mode */ clear_bit( PORTD, LCD_RS ); LCD_Delay(); } /***********************************/ /* Put LCD in Data Mode */ /***********************************/ void LCD_DataMode(void) { set_bit( ModeFlags, 0 ); /* Save Mode */ set_bit( PORTD, LCD_RS ); LCD_Delay(); } /***********************************/ /* Write a single byte to the LCD */ /* 8 Bit Mode */ /***********************************/ void LCD_Write_8_Bit(char d ) { clear_bit( d, LCD_WR ); /* Write mode */ clear_bit( d, LCD_RS ); /* Function mode */ clear_bit( d, LCD_SEL); PORTD = d; /* Setup data */ delay_ms(1); clear_wdt(); set_bit( PORTD, LCD_SEL); /* Select LCD */ LCD_Delay(); clear_bit( PORTD, LCD_SEL ); /* de-select LCD */ LCD_Delay(); clear_wdt(); } /***********************************/ /* Write a single byte to the LCD */ /* 4 Bit Mode */ /***********************************/ void LCD_Write_4_Bit(char d ) { char e; e = d; /* Save lower 4 bits */ /*********************************** Output Upper 4 bits ******************************/ clear_bit( d, LCD_WR ); /* Write mode */ if ( ( ModeFlags & 0x01 ) == 0 ) clear_bit( d, LCD_RS ); /* Function mode */ else set_bit( d, LCD_RS ); /* Data mode */ clear_bit( d, LCD_SEL); PORTD = d; /* Setup data */ delay_ms(1); set_bit( PORTD, LCD_SEL); /* Select LCD */ LCD_Delay(); clear_bit( PORTD, LCD_SEL ); /* de-select LCD */ d = e; /* Restore lower 4 bits */ d <<= 4; /*********************************** Output Lower 4 bits ******************************/ clear_bit( d, LCD_WR ); /* Write mode */ if ( ( ModeFlags & 0x01 ) == 0 ) clear_bit( d, LCD_RS ); /* Function mode */ else set_bit( d, LCD_RS ); /* Data mode */ clear_bit( d, LCD_SEL); PORTD = d; /* Setup data */ delay_ms(1); set_bit( PORTD, LCD_SEL); /* Select LCD */ LCD_Delay(); clear_bit( PORTD, LCD_SEL ); /* de-select LCD */ LCD_Delay(); } /***********************************/ /* LCD timing delay */ /* Adjust for your LCD */ /***********************************/ void LCD_Delay(void) { delay_ms(6); clear_wdt(); } /***********************************/ /* Clear LCD Screen */ /***********************************/ void LCD_Clear(void) { LCD_FunctionMode(); LCD_Write_4_Bit(clear_lcd); LCD_DataMode(); } /***********************************/ /* Set the cursor position */ /***********************************/ void LCD_SetPos(char Pos) { LCD_FunctionMode(); LCD_Write_4_Bit( Pos ); LCD_DataMode(); } /***********************************/ /* Set Position to line 1 */ /***********************************/ void LCD_Line_1(void) { LCD_FunctionMode(); LCD_Write_4_Bit( set_dd_line1 ); LCD_DataMode(); } /***********************************/ /* Set Position to line 2 */ /***********************************/ void LCD_Line_2(void) { LCD_FunctionMode(); LCD_Write_4_Bit( set_dd_line2 ); LCD_DataMode(); } /*******************************************/ /* Clear Line 1 */ /*******************************************/ void LCDClearLine1(void) { LCD_Line_1(); for( LCD_gp = 0; LCD_gp < 16; LCD_gp++ ) { LCD_Write_4_Bit(' '); } LCD_Line_1(); } /*******************************************/ /* Clear Line 2 */ /*******************************************/ void LCDClearLine2(void) { LCD_Line_2(); for( LCD_gp = 0; LCD_gp < 16; LCD_gp++ ) { LCD_Write_4_Bit(' '); } LCD_Line_2(); } /*******************************************/ /* Normal_Mode ( Cancels Shift mode ) */ /*******************************************/ void LCD_NormalMode(void) { LCD_FunctionMode(); LCD_Write_4_Bit( entry_mode ); LCD_DataMode(); } /*******************************************/ /* Shift_Mode ( Display Shifts ) */ /*******************************************/ void LCD_ShiftMode(void) { LCD_FunctionMode(); LCD_Write_4_Bit( entry_mode_shift ); LCD_DataMode(); } /*******************************************/ /* Write a const string to the LCD */ /*******************************************/ void WriteLCDString( const char *lcdptr ) { char pi; pi = 0; // Check for end of string while( lcdptr[pi] != 0 ) { LCD_Write_4_Bit( lcdptr[pi++] );// Display on LCD } } /*******************************************/ /* Write a const string to the LCD */ /*******************************************/ void WriteLCD( char *lcdptr ) { char pi; pi = 0; // Check for end of string while( lcdptr[pi] != 0 ) { LCD_Write_4_Bit( lcdptr[pi++] );// Display on LCD } }