CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

help cgram

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
xericklmx



Joined: 26 Feb 2014
Posts: 1

View user's profile Send private message

help cgram
PostPosted: Wed Feb 26, 2014 7:47 pm     Reply with quote

I need help with this library, I can not make a hand on the LCD screen, this library is called lcd_driver.h, found in libraries sourceboots


Code:

////////////////////////////////////////////////////////////////////////////
// LCD with HD44780 drive chip
////////////////////////////////////////////////////////////////////////////
// Author(s): David Hobday, Pavel Baranov
// Date 15 November 2004
//
// Copyright(C) 2004-2010 Pavel Baranov
// Copyright(C) 2004-2010 David Hobday
// Copyright(C) 2004 Andrew Smallridge
//
//
// How to use - by David Hobday
// ============================
// Remember when using LCD in 4 bit mode you must connect to the LCDs DB4-DB7 pins.
//
// *** For a list of functions, see the END of this file.
//
// The time delays used in the code should mean that it will work on PIC18 with
// 40MHz clock without any changes.
//
// The example below (which would work on a PIC16F84) operates the display
// in 4bit mode and requires the following connections:
// RS  to RA3
// R/W to RA2
// E   to RA1
// DB0 to None
// DB1 to None
// DB2 to None
// DB3 to None
// DB4 to RB4
// DB5 to RB5
// DB6 to RB6
// DB7 to RB7
//
//
// Add the following after #include <system.h> in you source file:
//
//#define LCD_ARGS    2,   /* Interface type: mode 0 = 8bit, 1 = 4bit(low nibble), 2 = 4bit(upper nibble) */ \
//      1,             /* Use busy signal: 1 = use busy, 0 = use time delays */\
//      PORTB, TRISB,    /* Data port and data port tris register */ \
//      PORTA, TRISA,    /* Control port and control port tris register */ \
//      3,            /* Bit number of control port is connected to RS */ \
//      2,            /* Bit number of control port is connected to RW */ \
//      1             /* Bit number of control port is connected to Enable */
//
//#include <lcd_driver.h> // include the LCD template code
//
//
// Revisions
// =========
//
// V1.10 David Hobday 03/03/2005
// =============================
// 1) Improved documentation in file
// 2) Changed delays to delay_10us for usage on target with clock <= 4MHz
// 3) Changed template to make more friendly and obvious
//
// V1.11 18/03/2005
// David Hobday
// 1) Fixed operation with PIC18 - template arguments of incorrect type
// 2) Tested with PicDem2Plus board (4MHz PIC16F877/PIC18F452)
// 3) Added lcd_gotoxy function.
// 4) Added option to use display busy bit or time delays
// 5) Added overloaded lprintf function for ROM string
// 6) Added overloaded lprintf function to output numbers supported formats:
//  "%d" - decimal
//  "%X" - hex
//  "%b" - binart
//  example: display binary number six digits, '0' as file character.
//  lprintf( "val:%06b", numb );
// 7) Other improvements/cleanup.
//
//
// V1.11 David Hobday 25/03/2005
// =============================
// 1) Fixed bug with lprintf( "test:%d", 0 ); not printing a 0.
// 2) Added a few more comments in lprintf( const char*, int ) code
//
//
// V1.12 Jason Sobell 03/07/2005
// =============================
// 1) Fixed display of unsigned integers >32767
//
//
// V1.13 David Hobday 08/07/2005
// =============================
// 1) Removed code that is no longer needed (as val is now unsigned).
// 2) Tweaked Jason Sobell changes a little to reduce code size.
//
//
// V1.14 David Hobday 11/11/2005
// =============================
// 1) Changed lcd_gotoxy function so that it works as expected with 20 x 4 display
//

////////////////////////////////////////////////////////////////////////////

char writeDelayType;

////////////////////////////////////////////////////////////////////////////
// LCD Commands ( Refer to LCD Data Sheet )
////////////////////////////////////////////////////////////////////////////
#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        0x38 // 8 bit data mode 2 line ( 5x7 font )
#define system_set_4_bit        0x28 // 4 bit data mode 2 line ( 5x7 font )
#define system_set_reset        0x30 // Reset code
#define display_on              0x0C // Display ON - 2 line mode
#define display_off             0x08 // Display off
#define set_dd_line1            0x40 // Line 1 position 1
#define set_dd_line2            0xC0 // Line 2 position 1
#define set_dd_ram              0x40 // 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

#define WriteNoDelay   1
#define WriteControlled   0

// Interface type
#define LCD_8_BIT_MODE 0
#define LCD_4_BIT_LO_NIB_MODE 1
#define LCD_4_BIT_HI_NIB_MODE 2

// These macros make susequent code more readable, but can seem a little confusing
#define _LCD_RawWriteNibble LCD_RawWriteNibble   <InterfaceType, UseBusy, DataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E>
#define _LCD_RawWriteNibbleInline  LCD_RawWriteNibbleInline   <InterfaceType, UseBusy, DataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E>
#define _LCD_Read         LCD_Read         <InterfaceType, UseBusy, DataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E>
#define _LCD_WaitForNotBusy   LCD_WaitForNotBusy   <InterfaceType, UseBusy, DataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E>
#define _LCD_Write         LCD_Write         <InterfaceType, UseBusy, DataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E>
#define _LCD_FunctionMode   LCD_FunctionMode   <InterfaceType, UseBusy, DataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E>
#define _LCD_DataMode      LCD_DataMode      <InterfaceType, UseBusy, DataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E>
#define _LCD_RawWrite      LCD_RawWrite      <InterfaceType, UseBusy, DataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E>
#define _LCD_ClockOut      LCD_ClockOut      <InterfaceType, UseBusy, DataPort, Data_PortTris, CtrlPort, Ctrl_PortTris, RS, RW, E>

#define _LCD_TEMPL      template <   unsigned char InterfaceType,\
                           unsigned char UseBusy,\
                           unsigned int DataPort, unsigned int Data_PortTris,\
                           unsigned int CtrlPort, unsigned int Ctrl_PortTris,\
                           unsigned char RS, unsigned char RW, unsigned char E>

_LCD_TEMPL
inline void LCD_FunctionMode( void )
{
   volatile bit rs@CtrlPort.RS = 0;
}

_LCD_TEMPL
inline void LCD_DataMode( void )
{
   volatile bit rs@CtrlPort.RS = 1;
}


inline void 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
   asm nop
   asm nop   
}


inline void LCD_EnablePulseDelay()
{      
   // PWEH > 460ns on Sharp data sheet
   // @40MHz this is 5 instructions
   asm nop
   asm nop
   asm nop
   asm nop
   asm nop
}

inline void LCD_SetupDelay()
{
   // tAS > 140ns min on Sharp data sheet
   // @40MHz this is 2 instructions
   asm nop
   asm nop
}

inline void LCD_HoldupDelay()
{
   // tAS > 10ns min on Sharp data sheet
   // @40MHz this is 1 instructions
   asm nop
}



_LCD_TEMPL
char LCD_Read()
{      
   char d;
   volatile unsigned char data@DataPort, tris@Data_PortTris;
   volatile bit rw@CtrlPort.RW, e@CtrlPort.E;
   
   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 )
   {
      // port input   
      tris = 0xFF;
      rw = 1; // set reading mode
      LCD_SetupDelay();
      e = 1;
      LCD_EnablePulseDelay();
      d = data;
      e = 0;
      LCD_HoldupDelay();
      LCD_CycleMakeupDelay();
   }
   
   return d;
}

_LCD_TEMPL
void 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@DataPort, tris@Data_PortTris;
   volatile bit rw@CtrlPort.RW, e@CtrlPort.E;
   
   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();
   }   
}

_LCD_TEMPL
inline void LCD_RawWriteNibbleInline( char d )
{
   // Note: this function is above, but declared inline.
   // this is to reduce stack depth usage
   volatile unsigned char data@DataPort, tris@Data_PortTris;
   volatile bit rw@CtrlPort.RW, e@CtrlPort.E;
   
   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();
   }   
}


_LCD_TEMPL
void LCD_RawWrite( char d )
{      
   volatile unsigned char tris@Data_PortTris, data@DataPort;
   volatile bit rw@CtrlPort.RW, e@CtrlPort.E;
      
   if( InterfaceType == LCD_4_BIT_HI_NIB_MODE  )
   {
      // output upper nibble, then lower nibble
      bit flag = 0;
      do
      {         
         _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 b output
      rw = 0; // set writing mode
      tris = 0x00;      
      data = d;
      LCD_SetupDelay();
      e = 1;
      LCD_EnablePulseDelay();
      e = 0;
      LCD_HoldupDelay();
      LCD_CycleMakeupDelay();
   }
}

_LCD_TEMPL
inline void LCD_WaitForNotBusy()
{
   volatile bit rs@CtrlPort.RS; bit old_RS = rs;   
   rs = 0;
   while( _LCD_Read() & 0x80 ); // wait while busy set
   rs = old_RS;
}

_LCD_TEMPL
void LCD_Write(char d )
{
   volatile bit rs@CtrlPort.RS;
   
   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!!         
      }
   }
}

_LCD_TEMPL
void LCD_Clear()
{
   _LCD_FunctionMode();
   _LCD_Write( clear_lcd ); // clear display
   _LCD_Write( return_home );
}

_LCD_TEMPL
void LCD_Setup( void )
{
   // set control port bits used to output
   volatile bit trisRS@Ctrl_PortTris.RS, trisRW@Ctrl_PortTris.RW, trisE@Ctrl_PortTris.E;
   trisRS = 0;
   trisRW = 0;
   trisE = 0;
   
   writeDelayType = WriteNoDelay; // no delays in data writes
   
   delay_ms(16); // Power up delay
   _LCD_FunctionMode();

   if( InterfaceType == LCD_4_BIT_HI_NIB_MODE )
   {
      // Reset sequence as described in data sheets
      _LCD_RawWriteNibble( system_set_reset );
      delay_ms(5); // min delay here of 4.1 ms
      _LCD_RawWriteNibble( system_set_reset );
      delay_10us(100); // min delay here of 100us
      _LCD_RawWriteNibble( system_set_reset );
      
      // LCD busy flag is valid from this point onwards
      if( UseBusy == 1 )
         _LCD_WaitForNotBusy();
      else
         delay_10us( 5 ); // standard command delay time
      
      _LCD_RawWriteNibble( system_set_4_bit );
      
      if( UseBusy == 1 )
         _LCD_WaitForNotBusy();
      else
         delay_10us( 5 ); // standard command delay time

      writeDelayType = WriteControlled;
      _LCD_Write( system_set_4_bit );
   }

   if( InterfaceType == LCD_4_BIT_LO_NIB_MODE )
   {
      // Reset sequence as described in data sheets
      _LCD_RawWriteNibble( system_set_reset );
      delay_ms(5); // min delay here of 4.1 ms
      _LCD_RawWriteNibble( system_set_reset );
      delay_10us(100); // min delay here of 100us
      _LCD_RawWriteNibble( system_set_reset );
      
      // LCD busy flag is valid from this point onwards
      if( UseBusy == 1 )
         _LCD_WaitForNotBusy();
      else
         delay_10us( 5 ); // standard command delay time
      
      _LCD_RawWriteNibble( system_set_4_bit );
      
      if( UseBusy == 1 )
         _LCD_WaitForNotBusy();
      else
         delay_10us( 5 ); // standard command delay time

      writeDelayType = WriteControlled;
      _LCD_Write( system_set_4_bit );
   }
   
   if( InterfaceType == LCD_8_BIT_MODE )
   {
      // Reset sequence as described in data sheets
      _LCD_RawWrite( system_set_reset );
      delay_ms(5); // min delay here of 4.1 ms
      _LCD_RawWrite( system_set_reset );
      delay_10us(10); // min delay here of 100us
      _LCD_RawWrite( system_set_reset );
      
      // busy flag is valid from this point onwards
      if( UseBusy == 1 )
         _LCD_WaitForNotBusy();
      else
         delay_10us( 5 ); // standard command delay time

      _LCD_RawWrite( system_set_8_bit );   

      if( UseBusy == 1 )
         _LCD_WaitForNotBusy();
      else
         delay_10us( 5 ); // standard command delay time
      
      writeDelayType = WriteControlled; // use busy
   }
      
   _LCD_Write( entry_mode );
   _LCD_Write( display_on );
   _LCD_Write( set_dd_ram );
}

_LCD_TEMPL
void 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
   }
}

_LCD_TEMPL
void 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
   }
}

_LCD_TEMPL
void LCD_Printf( const char *lcdptr, unsigned int val ) // JS - Accept unsigned by default
{
   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 ] = '\0';
         
         bit first = true;            
         while( bi )
         {
            bi--;
            if( val || first )
            {
               first = false;
                              
               if( baseOrBits == 10 )
               {
                  c = (unsigned char)(val % 10);   // JS - Optimization, use absolute of 10
                  val /= 10;   // JS - Optimization, use absolute of 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;
      }
   }
}

_LCD_TEMPL
void 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 +0x40);
}


_LCD_TEMPL
void LCD_Function( char func )
{
   _LCD_FunctionMode();
   _LCD_Write( func );
}

////////////////////////////////////////////////////////////////////////////
// Helpers that hide template arguments
////////////////////////////////////////////////////////////////////////////
// low level functions
#define lcd_write      LCD_Write<LCD_ARGS>
#define lcd_waitfornotbusy LCD_WaitForNotBusy<LCD_ARGS>
#define lcd_read      LCD_Read<LCD_ARGS>
#define lcd_funcmode   LCD_FunctionMode<LCD_ARGS>
#define lcd_datamode   LCD_DataMode<LCD_ARGS>


// high level functions - these all set function or data mode as required
#define lcd_setup      LCD_Setup<LCD_ARGS>
#define lprintf         LCD_Printf<LCD_ARGS>
#define lcd_clear      LCD_Clear<LCD_ARGS>
#define lcd_gotoxy      LCD_GotoXy<LCD_ARGS>
#define lcd_function    LCD_Function<LCD_ARGS>
oxo



Joined: 13 Nov 2012
Posts: 219
Location: France

View user's profile Send private message

PostPosted: Thu Feb 27, 2014 1:28 am     Reply with quote

How can anyone help? You don't tell us what the hardware is, you dont say what PIC, you don't say what the problem is..

It's like you going to the garage without your car, and asking them to fix it. All you tell them is that it's a ford...
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group