Jump to content

knn10

Members
  • Content Count

    4
  • Joined

  • Last visited

Community Reputation

0 Neutral

About knn10

  • Rank
    Newbrie
  1. This is a limitation of the current compiler. We plan to fix it but this won't happen soon because the cause of the problem is in third-party code that we have little control of. Not sure what you mean by "even though CtrlPort = PORTA;" but with your defines after preprocessor replaces all macros the code will look like: volatile bit rs@= PORTA.= 2 = 1; what from compiler point is total garbage. Regards, Pavel Touche on the defines... error on my part. The reason the declared and initialized variables would not work is still in question in my mind. why is the compiler unable to replace variables in the: volatile bit rs@CtrlPort.RS; statement when Class PCM_LCD{ private: . . . unsigned int CtrlPort; unsigned char RS; . . . }; void PCM_LCD::PCM_LCD( ..., unsigned int CPORT, unsigned char RS_Temp, ... ) { //Class constructor . . . CtrlPort = CPORT; RS = RS_Temp; . . . } Is defined as a private class members are created and initialized as above in the class constructor... Assuming CPORT = PORTA and RS_Temp = 2 So when volatile bit rs@CtrlPort.RS = 1; is defined in another member function of the class - should it not be equivalent to rs@PORTA.2 ? So why does the compiler grip about the lack of a "fixed address" when the address is given by reference to PORTA throgh the assignment to CtrlPort in the constructor? I'd appreciate your ideas and thoughts on this...
  2. Hi Pavel, Thanks for the quick help. That does not seem to be a standard C++ programming convention. Typically, the class identifier is used during the definition of the class object (in the .h file), but not in the declaration of the defined object (in the .c file)... This convention seems a little strange, why does the compiler require class declaration to be done this way? Thanks for the help on this. I'll give it a shot tommorrow. Another problem I ran into was in my attempt to define I/O variables in the class where say : volatile bit rs@CtrlPort.RS = 1; The compiler issued error becuase of lack of "fixed address" even though CtrlPort = PORTA; and RS=2; Even tried using #define CtrlPort = PORTA #define RS = 2 No luck... I worked around this by replacing the variables with PORT identifiers like PORTA and PORTD and actual bit numbers such as rs@PORTA.2 = 1; Any idea what I was doing wrong there? How can I implement the code using variables? Or will I just have to stick with the work around I cam up with? Thanks again, Nate From BoostC++ help: "...The class keyword must always be used when declaring a class data type..." Regards, Pavel
  3. Here is the code: //////////////////////////////////////////////////////////////////////////// // Production Counter Module - LCD Driver Class //////////////////////////////////////////////////////////////////////////// // Author: Nate Nivens // October 27, 2007 // Original C Source Code - lcd_driver.h by SourceBoost // Custom class adaptation of LCD driver provided with SourceBoost C++ compiler // Designed to operate with DCI081A LCD Module or // ABC008001A06-TGN-R (B/W version) provided by AV Display (North America) Ltd // Added power and LCD contrast ON/OFF controls // // How to use // ========== // Remember if using LCD in 4 bit mode you must connect to the LCDs DB4-DB7 pins. // // Present hardware uses 8 bit mode for fast operation to minimize processor awake time. // // The example below (designed for use on Microchip PIC16F917 40 PDIP) operates the display // in 8bit mode and requires the following connections: // LCD_PWR to RA0 // LCD_CON to RA1 // RS to RA2 // R/W to RA3 // E to RA4 // DB0 to RD0 // DB1 to RD1 // DB2 to RD2 // DB3 to RD3 // DB4 to RD4 // DB5 to RD5 // DB6 to RD6 // DB7 to RD7 // // // Class Initilization Variables: // // 0, /* Interface type: mode 0 = 8bit, 1 = 4bit(low nibble), 2 = 4bit(upper nibble) */ // 1, /* Use busy signal: 1 = use busy, 0 = use time delays */ // PORTD, TRISD, /* Data port and data port tris register */ // PORTA, TRISA, /* Control port and control port tris register */ // 0, /* Bit number of control port is connected to LCD Vdd(+) controls ON(1)/OFF(0) // 1, /* Bit number of control port is connected to LCD V5 (Volage Divider Contrast Control) controls ON(1)/OFF(0) // 2, /* Bit number of control port is connected to RS */ // 3, /* Bit number of control port is connected to RW */ // 4, /* Bit number of control port is connected to Enable */ // // // See PCM_LCD Class constructor below for more information // #include "PCM_LCD.h" // include the LCD class code // Note: Be sure PCM_LCD.h is in the project directory //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// // LCD Commands ( Refer to LCD Data Sheet ) // NN Note: Using Specification DCI081A based on Samsung Data Book S6A0069(KS0066U) //////////////////////////////////////////////////////////////////////////// #define clear_lcd 0x01 // Clear Display #define return_home 0x02 // Cursor to Home position #define entry_mode 0x06 // Normal entry mode #define entry_mode_rev 0x04 // Normal entry mode -reverse direction #define entry_mode_scroll 0x07 // - with shift #define entry_mode_scroll_rev 0x05 // reverse direction #define system_set_8_bit 0x3C // 8 bit data mode 1 line ( 5x11 font ) #define system_set_4_bit 0x2C // 4 bit data mode 1 line ( 5x11 font ) #define display_on 0x0C // Display ON (Display is not same as module power) #define display_off 0x08 // Display OFF (Display is not same as module power) #define set_dd_line1 0x00 // Line 1 position 1 #define set_dd_line2 0x40 // Line 2 position 1 #define set_dd_ram 0x00 // 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 #define cursor_blink_on 0x0F // Cursor plus blink #define cursor_shift_right 0x14 // Move cursor right #define cursor_shift_left 0x10 // Move cursor left #define display_shift_right 0x1C // Scroll display right #define display_shift_left 0x18 // Scroll display left // LCD Write Control #define WriteNoDelay 1 #define WriteControlled 0 // Interface type #define LCD_8_BIT_MODE 0 // Uses DB0 thru DB7 (eight bit data transfer) #define LCD_4_BIT_LO_NIB_MODE 1 // Uses DB0 thru DB3 (four bit data transfer) #define LCD_4_BIT_HI_NIB_MODE 2 // Uses DB4 thru Db7 (four bit data transfer) // Hardware Specific LCD Parameters Defined: //#define InterfaceType = 0 //#define UseBusy = 1 //#define DataPort = PORTD //#define Data_PortTris = TRISD //#define CtrlPort = PORTA //#define Ctrl_PortTris = TRISA //#define LCD_PWR = 0 //#define LCD_CON = 1 //#define RS = 2 //#define RW = 3 //#define E = 4 // Class Definition Below: class PCM_LCD{ private: unsigned char InterfaceType; unsigned char UseBusy; unsigned int DataPort; unsigned int Data_PortTris; unsigned int CtrlPort; unsigned int Ctrl_PortTris; unsigned char LCD_PWR; unsigned char LCD_CON; unsigned char RS; unsigned char RW; unsigned char E; char writeDelayType; public: void PCM_LCD(); void LCD_Power_ON( void ); void LCD_Power_OFF( void ); void LCD_FunctionMode( void ); void LCD_DataMode( void ); void LCD_CycleMakeupDelay(); void LCD_EnablePulseDelay(); void LCD_SetupDelay(); void LCD_HoldupDelay(); char LCD_Read(); void LCD_RawWriteNibble( char d ); void LCD_RawWriteNibbleInline( char d ); void LCD_RawWrite( char d ); void LCD_WaitForNotBusy(); void LCD_Write(char d ); void LCD_Clear(); void LCD_Setup( void ); void LCD_Printf( const char *lcdptr ); void LCD_Printf( rom char *lcdptr ); void LCD_Printf( const char *lcdptr, unsigned int val ); void LCD_GotoXy( char x, char y ); void LCD_Function( char func ); }; void PCM_LCD::PCM_LCD() { //Object Constructor & Initilization InterfaceType = 0; UseBusy = 1; DataPort = PORTD; Data_PortTris = TRISD; CtrlPort = PORTA; Ctrl_PortTris = TRISA; LCD_PWR = 0; LCD_CON = 1; RS = 2; RW = 3; E = 4; //Set writeDelayType Variable - Using hardware reading writeDelayType = WriteControlled; LCD_Power_OFF(); } void PCM_LCD::LCD_Power_ON( void ) { // Turns on the LCD Module Power volatile bit lcd_pwr@PORTA.0 = 1; // Turns on the Contrast Voltage Divider volatile bit lcd_con@PORTA.1 = 1; // Initialize the LCD Module LCD_Setup(); } void PCM_LCD::LCD_Power_OFF( void) { // Turns off power to the LCD Module volatile bit lcd_pwr@PORTA.0 = 0; // Turns off power to the Contrast Voltage Divider volatile bit lcd_con@PORTA.1 = 0; } void PCM_LCD::LCD_FunctionMode( void ) { // Set the RS line low to signal function mode volatile bit rs@PORTA.2 = 0; } void PCM_LCD::LCD_DataMode( void ) { // Set the RS line high to signal data mode volatile bit rs@PORTA.2 = 1; } void PCM_LCD::LCD_CycleMakeupDelay() { // Enable cycle time must be > 1000ns total for both reading and writing // LCD_SetupDelay + LCD_EnablePulseDelay + LCD_HoldupDelay + LCD_CycleMakeupDelay >= 1000ns // 200 + 500 + 100 + 200 >= 1000ns // This delay is required to meet the Sharp data sheet total cycle time of > 1000ns // @40MHz this is 2 instructions // NN Note: May need to change this to meet Samsung Specs asm nop asm nop } void PCM_LCD::LCD_EnablePulseDelay() { // tc > 500ns on per data sheet // @40MHz this is 5 instructions // NN Note: Will need to change this to meet Samsung Specs asm nop asm nop asm nop asm nop asm nop } void PCM_LCD::LCD_SetupDelay() { // tSU > 40ns min per data sheet // @40MHz this is 2 instructions asm nop asm nop } void PCM_LCD::LCD_HoldupDelay() { // tH > 10ns min per data sheet // @40MHz this is 1 instructions asm nop } char PCM_LCD::LCD_Read() { char d; volatile unsigned char data@PORTD, tris@TRISD; volatile bit rw@PORTA.2, e@PORTA.4; if( InterfaceType == LCD_4_BIT_HI_NIB_MODE ) { // upper nibble input tris |= 0xF0; rw = 1; // set reading mode // first high nibble LCD_SetupDelay(); e = 1; LCD_EnablePulseDelay(); d = data & 0xF0; // read data e = 0; LCD_HoldupDelay(); LCD_CycleMakeupDelay(); // then low nibble LCD_SetupDelay(); e = 1; LCD_EnablePulseDelay(); d |= data >> 4; e = 0; LCD_HoldupDelay(); LCD_CycleMakeupDelay(); } if( InterfaceType == LCD_4_BIT_LO_NIB_MODE ) { // lower nibble input tris |= 0x0F; rw = 1; // set reading mode // first high nibble LCD_SetupDelay(); e = 1; LCD_EnablePulseDelay(); d = data << 4; e = 0; LCD_HoldupDelay(); LCD_CycleMakeupDelay(); // then low nibble LCD_SetupDelay(); e = 1; LCD_EnablePulseDelay(); d |= data & 0x0F; e = 0; LCD_HoldupDelay(); LCD_CycleMakeupDelay(); } if( InterfaceType == LCD_8_BIT_MODE ) { // Set port to input tris = 0xFF; rw = 1; // set reading mode LCD_SetupDelay(); e = 1; LCD_EnablePulseDelay(); d = data; e = 0; LCD_HoldupDelay(); LCD_CycleMakeupDelay(); } return d; } void PCM_LCD::LCD_RawWriteNibble( char d ) { // Note: this function is duplicate below, but declared inline. // this is to reduce stack depth usage // Note: this function is above, but declared inline. // this is to reduce stack depth usage volatile unsigned char data@PORTD, tris@TRISD; volatile bit rw@PORTA.3, e@PORTA.4; if( InterfaceType == LCD_4_BIT_HI_NIB_MODE ) { // port upper nibble output rw = 0; // set writing mode LCD_SetupDelay(); tris &= 0x0F; data &= 0x0F; data |= d & 0xF0; e = 1; LCD_EnablePulseDelay(); e = 0; LCD_HoldupDelay(); LCD_CycleMakeupDelay(); } if( InterfaceType == LCD_4_BIT_LO_NIB_MODE ) { // port upper nibble output rw = 0; // set writing mode LCD_SetupDelay(); tris &= 0xF0; data &= 0xF0; data |= d >> 4; e = 1; LCD_EnablePulseDelay(); e = 0; LCD_HoldupDelay(); LCD_CycleMakeupDelay(); } } void PCM_LCD::LCD_RawWriteNibbleInline( char d ) { // Note: this function is above, but declared inline. // this is to reduce stack depth usage volatile unsigned char data@PORTD, tris@TRISD; volatile bit rw@PORTA.3, e@PORTA.4; if( InterfaceType == LCD_4_BIT_HI_NIB_MODE ) { // port upper nibble output rw = 0; // set writing mode LCD_SetupDelay(); tris &= 0x0F; data &= 0x0F; data |= d & 0xF0; e = 1; LCD_EnablePulseDelay(); e = 0; LCD_HoldupDelay(); LCD_CycleMakeupDelay(); } if( InterfaceType == LCD_4_BIT_LO_NIB_MODE ) { // port upper nibble output rw = 0; // set writing mode LCD_SetupDelay(); tris &= 0xF0; data &= 0xF0; data |= d >> 4; e = 1; LCD_EnablePulseDelay(); e = 0; LCD_HoldupDelay(); LCD_CycleMakeupDelay(); } } void PCM_LCD::LCD_RawWrite( char d ) { volatile unsigned char tris@TRISD, data@PORTD; volatile bit rw@PORTA.3, e@PORTA.4; if( InterfaceType == LCD_4_BIT_HI_NIB_MODE ) { // output upper nibble, then lower nibble bit flag = 0; do { this.LCD_RawWriteNibbleInline( d ); flag = !flag; d <<= 4; } while( flag ); } if( InterfaceType == LCD_4_BIT_LO_NIB_MODE ) { // output upper nibble, then lower nibble bit flag = 0; do { LCD_RawWriteNibbleInline( d ); flag = !flag; d <<= 4; } while( flag ); } if( InterfaceType == LCD_8_BIT_MODE ) { // port D output rw = 0; // set writing mode tris = 0x00; data = d; LCD_SetupDelay(); e = 1; LCD_EnablePulseDelay(); e = 0; LCD_HoldupDelay(); LCD_CycleMakeupDelay(); } } void PCM_LCD::LCD_WaitForNotBusy() { volatile bit rs@PORTA.2; bit old_RS = rs; rs = 0; while( LCD_Read() & 0x80 ); // wait while busy set rs = old_RS; } void PCM_LCD::LCD_Write(char d ) { volatile bit rs@PORTA.2; if( UseBusy == 1 ) { // wait until display Not busy before sending next data if ( writeDelayType == WriteControlled ) LCD_WaitForNotBusy(); LCD_RawWrite( d ); } else { LCD_RawWrite( d ); // give time to complete if ( writeDelayType == WriteControlled ) { if( !rs && (d == return_home || d == clear_lcd) ) delay_ms( 2 ); // return_home takes more time than other instructions to execute else delay_10us( 5 ); // 50us - enough time for normal command execution - clear and home need longer!! } } } void PCM_LCD::LCD_Clear() { LCD_FunctionMode(); LCD_Write( clear_lcd ); // clear display LCD_Write( return_home ); } void PCM_LCD::LCD_Setup( void ) { // set control port bits used to output volatile bit trisRS@TRISA.2, trisRW@TRISA.3, trisE@TRISA.4; // Set RS pin as output trisRS = 0; // Set RW pin as output trisRW = 0; // Set E pin as output trisE = 0; // Setup no delays in data writes writeDelayType = WriteNoDelay; // Power up delay per LCD specs delay_ms(30); // Set RS to signal Function Commands LCD_FunctionMode(); // Execute this code if set to operate in 4 Bit High Nibble Mode if( InterfaceType == LCD_4_BIT_HI_NIB_MODE ) { // LCD busy flag is valid from this point onwards if( UseBusy == 1 ) LCD_WaitForNotBusy(); else delay_10us( 5 ); // standard command delay time // Function Set per specs LCD_RawWriteNibble( system_set_4_bit ); if( UseBusy == 1 ) LCD_WaitForNotBusy(); else delay_10us( 5 ); // standard command delay time writeDelayType = WriteControlled; // Function Set per specs LCD_Write( system_set_4_bit ); } // Execute this code if set to operate in 4 Bit Low Nibble Mode if( InterfaceType == LCD_4_BIT_LO_NIB_MODE ) { // LCD busy flag is valid from this point onwards if( UseBusy == 1 ) LCD_WaitForNotBusy(); else delay_10us( 5 ); // standard command delay time // Function Set per specs LCD_RawWriteNibble( system_set_4_bit ); if( UseBusy == 1 ) LCD_WaitForNotBusy(); else delay_10us( 5 ); // standard command delay time writeDelayType = WriteControlled; // Function Set per specs LCD_Write( system_set_4_bit ); } //Execute this code if set to operate in 8 Bit Mode if( InterfaceType == LCD_8_BIT_MODE ) { // busy flag is valid from this point onwards if( UseBusy == 1 ) LCD_WaitForNotBusy(); else delay_10us( 5 ); // standard command delay time // Function Set per specs LCD_RawWrite( system_set_8_bit ); if( UseBusy == 1 ) LCD_WaitForNotBusy(); else delay_10us( 5 ); // standard command delay time writeDelayType = WriteControlled; // use busy } // The following depends on the use of the LCD_WaitForNotBusy() inside LCD_Write() // for necessary timing delays LCD_Write( display_on ); LCD_Write( clear_lcd ); LCD_Write( entry_mode ); LCD_Write( return_home ); // At this point LCD Module is initialized and ready to be used use LCD_Printf() } void PCM_LCD::LCD_Printf( const char *lcdptr ) { char pi = 0, c; LCD_DataMode(); while( 1 ) { c = lcdptr[pi++]; if ( !c ) return; if ( c == '\n' ) { LCD_FunctionMode(); // move to start second line LCD_Write( set_dd_ram + 0x40 ); LCD_DataMode(); } else LCD_Write( c );// Display on LCD } } void PCM_LCD::LCD_Printf( rom char *lcdptr ) { char pi = 0, c; LCD_DataMode(); while( 1 ) { c = lcdptr[pi++]; if ( !c ) return; if ( c == '\n' ) { LCD_FunctionMode(); // move to start second line LCD_Write( set_dd_ram + 0x40 ); LCD_DataMode(); } else LCD_Write( c );// Display on LCD } } void PCM_LCD::LCD_Printf( const char *lcdptr, unsigned int val ) { unsigned char pi = 0, bi, c, fill, baseOrBits, sign, mask; unsigned char buff[ 10 ]; // max length allow is 9 bit pad; LCD_DataMode(); while( 1 ) { c = lcdptr[pi++]; if ( !c ) return; switch( c ) { case '\n': LCD_FunctionMode(); // move to start second line LCD_Write( set_dd_ram + 0x40 ); LCD_DataMode(); break; case '%': c = lcdptr[pi++]; if ( !c ) return; //Handle escape sequence that prints '%' if ( c == '%' ) { LCD_Write( c );// Display on LCD break; } // Next character if zero indicates that we should zero fill output if ( c == '0' ) { fill = '0'; c = lcdptr[pi++]; if ( !c ) return; } else fill = ' '; // Next character if valid digit indicates field width if( c > '0' && c <= '9' ) { pad = 1; bi = c - 48;; c = lcdptr[pi++]; if ( !c ) return; } else { pad = 0; bi = sizeof( buff ) - 1; } // Next character indicates the radix (number base) sign = 0; switch( c ) { case 'd': if( val & 0x8000 ) // Negative values must be adjusted to be positive // JS { sign = '-'; val ^= 0xFFFF; // 2s complement negate // JS val++; } case 'u': baseOrBits = 10; // base ten, divide by ten per digit break; case 'X': baseOrBits = 4; // base 16, requires a 4 bit shift per digit mask = 0x0F; break; case 'b': baseOrBits = 1; // base 16, requires a 1 bit shift per digit mask = 0x01; break; default: return; // no radix } // null terminate, then reverse fill string buff[ bi ] = '\'; bit first = true; while( bi ) { bi--; if( val || first ) { first = false; if( baseOrBits == 10 ) { c = (unsigned char)(val % 10); val /= 10; } else { c = val & mask; val = ((unsigned int)val) >> baseOrBits; } if( c > 9 ) c += 55; // convert to hex digits character A-F else c += 48; // convert to digit character 0-9 } else { if( sign && (bi == 0 || fill != '0') ) { c = sign; sign = 0; } else c = fill; } buff[ bi ] = c; if( pad == 0 && val == 0 && sign == 0 ) break; } // output string to display while( 1 ) { c = buff[ bi ]; if( !c ) break; LCD_Write( c );// Display on LCD bi++; } break; default: LCD_Write( c );// Display on LCD break; } } } void PCM_LCD::LCD_GotoXy( char x, char y ) { // displays memory mapping with two lines: // line 1: 0x00 // line 2: 0x40 // display memory mapping with four lines: // line 1: 0x00 // line 2: 0x40 // line 3: 0x14 // line 4: 0x54 LCD_FunctionMode(); unsigned char offset = x; if( y & 0x01 ) offset += 0x40; if( y & 0x02 ) offset += 0x14; LCD_Write( set_dd_ram + offset ); } void PCM_LCD::LCD_Function( char func ) { LCD_FunctionMode(); LCD_Write( func ); } Here is the test.c file: #include <system.h> #include "PCM_LCD.h" #pragma CLOCK_FREQ 4000000 void main() { PCM_LCD TheLCD; } This gives me a "semicoln missing error" every time I try to compile the code. PCM_LCD.h is included in the SourceBoost IDE project. Using registered SourceBoost C++ current release. I would appreciate any help or explanation as to why this code fails to compile and create the well defined class object. Thanks, Nate
  4. Hello, How does Novo RTOS handle MCU sleep commands? MCU sleep is necessary in many ultra low power applications. Can the MCU be put into sleep mode and woken up by hardware interrupt? Can the RTOS be used with the WDT? I'm new to RTOS usage forgive the nub questions... Regards, Nate
×
×
  • Create New...