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

I2C Slave firmware - problem debugging
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Wed Jan 21, 2004 6:52 am     Reply with quote

You can email me the spreadsheets and I will take a look and it is not a bother. If I didn't want to help, then I wouldn't be here. Very Happy
kda406



Joined: 17 Sep 2003
Posts: 97
Location: Atlanta, GA, USA

View user's profile Send private message

PostPosted: Wed Jan 21, 2004 7:57 am     Reply with quote

Hello guys. I am in testing right now, but appear to have a successful I2C slave 16F818 running on the 1 MHz internal RC. I am using Kenny's C port of AN734 with one very important modification.

Using Kenny's latest (clock stretching) AN734 C port, you can get all 5 of MicroChip's "states" successfully with a 16F818. But after a complete write/read operation (which does have two start states in a single "transaction") the <P>, i2c_stop() that the master sends will cause the 16F818 to throw an additional interrupt. It becomes a 6th state (SSPSTAT == 0x30), which AN734 does not handle and hangs the processor in the ISR (unless the WDT is enabled). Got that? Wink

To make it work on the 16F818, I added a simple if statement to allow the ISR to ignore the 6th state and return to normal program execution. I'm not saying it is the best way to handle it, but it appears to work, and should also be portable to other devices such as the 16F877 which do not experience this issue. Also, in later 16F818's when they fix the hardware issue, this code should still work because a SSPTAT 0x30 ISR will not be thrown.

I do not feel like my testing and changes to Kenny's port of AN734 is fully complete. But I do feel it works well enough to post to this thread as a probable solution to the slave 16F818 multiple start state issue. I hope it helps you guys and would be grateful to hear of any changes or upgrades that you make to what I have submitted below.

-Kyle

P.S. I have found this to work at slower speeds. I only run at 1 MHz because I am also running RS232 for debugging on the 16F818 and I don't want the serial communications to affect the code I am trying to debug.

16F818 Modified AN734 I2C Slave Code:
Code:
#include "I2CSlave.h"

// i2c slave pic code, a C translation of Microchip AN734.
// Slave pic must have i2c hardware (SSP)

/* Registers and bits associated with i2c Sync Serial Port
   Some of the comments apply only to the Master */
//For 16F877 & 16F818:
#byte SSPADD = 0x93  // Slave address held here
#byte SSPCON1= 0x14  // SSP control reg 1
#byte SSPCON2= 0x91  // SSP control reg 2
#byte SSPBUF = 0x13  // Buffer for SSP data
#byte SSPSTAT= 0x94  // SSP status reg

// SSPSTAT bits
#bit BF = SSPSTAT.0  // Buffer full status bit. Read-only bit.
                     // Receive mode 1 = SSPBUF full.
                     // Tx mode 1 = data transmit in progress, SSPBUF full.
                     // 0 = complete, SSPBUF empty.
                     // (does not include ack and stop bits in either case)
#bit UA = SSPSTAT.1  // User needs to update addr. in SSPADD, 10 bit mode only.
#bit R_W = SSPSTAT.2 // Holds read/write status from last address match, valid
                     // to next start,stop, or not /ack bit.
                     // Slave mode 1 = read, Master mode transmit in progress.
#bit START=SSPSTAT.3 // Start bit (S) has been detected last
#bit STOP= SSPSTAT.4 // Stop bit (P) has been detected last
#bit D_A = SSPSTAT.5 // Data/addr bit. 1 = last byte received or transmitted
                     // was data.
#bit CKE = SSPSTAT.6 // 0 = input levels are i2c specs, 1 = SMB specs.
#bit SMP = SSPSTAT.7 // Slew rate control. 1 = disabled for 100kHz or 1MHz modes


// SSPCON bits                                 /* Slave mode 7 bits */
#bit SSPM0 = SSPCON1.0  // SSP mode bits                 0
#bit SSPM1 = SSPCON1.1  // "                             1
#bit SSPM2 = SSPCON1.2  // "                             1
#bit SSPM3 = SSPCON1.3  // "                             0
#bit CKP   = SSPCON1.4  // Clock, 1 = enable clock, 0 = clock stretch
#bit SSPEN = SSPCON1.5  // SSP enable bit
#bit SSPOV = SSPCON1.6  // Receive overflow indicator bit. In receive mode, a
                        // byte is received while the SSPBUF is holding
                        // previous byte. Must clear in software.
#bit WCOL  = SSPCON1.7  // Write collision detect bit. In slave mode, 1 means
                        // SSBUF written while transmitting previous word.
                        // Must clear in software.

// SSPCON2 bits
/* Bits 0 to 6 are for Master only */
#bit SEN    = SSPCON2.0 // Initiate Start on SDA & SCL, hardware clears
#bit RSEN   = SSPCON2.1 // Initiate repeated start, hardware clears
#bit PEN    = SSPCON2.2 // Initiate Stop on SCA & SCL, hardware clears
#bit RCEN   = SSPCON2.3 // Enables i2c receive mode
#bit ACKEN  = SSPCON2.4 // Initiate Ack on SDA & SCL, xmit ACKDT bit, h/w clears
#bit ACKDT  = SSPCON2.5 // Master receive mode only. Acknowledge bit, value
                        // sent when user initiates ack sequence after receive
#bit ACKSTAT= SSPCON2.6 // Master transmit mode, 1 = ack not received from slave

#bit GCEN   = SSPCON2.7 // General call enable bit (slave mode only)

/* Other regs */
#byte TRISB = 0x86
//#byte INTCON = 0x8b
//#byte STATUS = 0x83
//#byte PIE1 = 0x8c
//#bit RBIF = INTCON.0      // The general interupt flag for SSP

#define SLAVE_ADDR  0x40   // Even number, must match address sent by Master
                           // Read address from Master is Slave address + 1.

#define BUF_LEN 33
int8 buf[BUF_LEN];         // Buffer for data to be received or transmitted
int8 buf_index;

// Possible i2c states, SSPSTAT for the four relevant bits
#define STATE1 0x09  // D/A=0,S=1,R/W=0,BF=1. Master tx, slave addr
#define STATE2 0x29  // D/A=1,S=1,R/W=0,BF=1. Master tx, data
#define STATE3 0x0C  // D/A=0,S=1,R/W=1,BF=0. Master rx, slave addr+1
#define STATE4 0x2C  // D/A=1,S=1,R/W=1,BF=0. Master rx, data with /ack
#define STATE5 0x28  // D/A=1,S=1,R/W=0,BF=0. Master rx, data with not /ack
//#define STATE6 0x30   // D/A=0,

// i2c interrupt handler
#int_SSP
SSP_isr() {
   output_high(LEDIRQ);
// Kenny, here I kept getting stuck at the end of a transmission, state 0x30
// which is D/A = 1 and also P = 1.  P isn't covered by the state definitions
// and is really just a "throw away" interupt saying that we received a stop
// condition.  I solved the problem by adding the extra if statement below:
   if(SSPSTAT != 0x30) {
      switch (SSPSTAT & 0x2d) {  // Keep only bits D/A, S, R/W, BF
         case(STATE1):
         // Master write operation, address byte in SSPBUF.
         // Clear the data buffer. Master must allow sufficient time
         // for this to finish before sending data byte(s). Otherwise SSPBUF
         // will be full and an acknowledge will not be generated by the slave
         // i2c hardware.
            CKP = 0;         // Make Master wait by holding SCL low

            for (buf_index = 0; buf_index < BUF_LEN; buf_index++) {
               buf[buf_index] = 0;
            }

            buf_index = 0; // Reset the data buffer index
            SSPOV = 0;     // Clear address overflow flag, could be set from last
                           // time because after not /ack, SSPBUF was still full.
            buf[buf_index] = SSPBUF;   // Dummy read to clear BF (read only bit)
            CKP = 1;       // Allow master to continue by re-enabling SCL
            break;

         case(STATE2):
         // Master write operation, data byte in SSPBUF.
         // Get data byte, also clears BF.
            SSPOV = 0;
            buf[buf_index] = SSPBUF;
            CKP = 0;       // Make Master wait by holding SCL low

//         output_b(buf[buf_index]);  // For debugging

            buf_index++;

            // Wrap around, should never occur
            if (buf_index > BUF_LEN) buf_index = 0;
            CKP = 1;       // Allow master to continue by re-enabling SCL
            break;

         case(STATE3):
         // Master has begun new read operation by initiating a START or RESTART
         // then sending Slave address (read) byte (now in SSPBUF).
         // Looks like clock enable bit CKP cleared on interrupt, so must
         // set it again to allow Master to clock data byte out.
         // SCL held low, Master can be kept waiting here if necessary.
            CKP = 0;       // Make Master wait by holding SCL low
         // delay_ms(5000);            // For testing clock stretching only

            buf_index = 0;             // Reset buffer index
            SSPBUF = buf[buf_index];   // Load 1st byte from data buffer
            buf_index++;
            CKP = 1;                   // Enable SCL for Master to shift byte out
            break;

         case(STATE4):
         // Master read operation, last byte was data, SSPBUF empty.
         // Move next byte to SSPBUF and SSPSR.
         // Same comment for CKP bit as in STATE3.
            CKP = 0;       // Make Master wait by holding SCL low
            SSPBUF = buf[buf_index];   // Get next byte from data buffer
            buf_index++;
            if (buf_index > BUF_LEN) buf_index = 0;
            CKP = 1;                   // Enable SCL for Master to shift byte out
            break;

         case(STATE5):
         // A not /ack (high) was received from Master in response to data
         // byte received from Slave (last byte). Slave i2c logic is reset,
         // and waits for next Master operation.
            break;
         default:
         // Error, trap here. Watchdog will reset pic (must be enabled, and
         // watchdog timer cleared in other loops).
            fprintf(HOSTPC,"Error: %X",SSPSTAT);
            while(1);
            break;
      }
   }
   output_low(LEDIRQ);
}

void init_i2c() {
   TRISB |= 0x12;               // Make the I2C Pins inputs
   SSPCON1 = 0b00110110;   // i2c slave mode, 7-bit address, enable SSP
   SSPADD = SLAVE_ADDR;    // Set slave address
}


void main() {
   int8 i;

   setup_oscillator(OSC_1MHZ);
   fprintf(HOSTPC,"\n\rProgram begin...\n\r");
   enable_interrupts(INT_SSP);
   enable_interrupts(GLOBAL);
   init_i2c();

   /* Loop continuously, flashing LED */
   while(1) {
      LED_ON;
      delay_ms(500);
      LED_OFF;
      delay_ms(500);
   }
}


Slave Header File:
Code:
#include "16F818.h"

//#define SYSTEMCLOCK 31000   //31 kHz RC
//#define SYSTEMCLOCK 125000      //125 KHz RC
#define SYSTEMCLOCK 1000000   //1 MHz RC
#use delay(clock=SYSTEMCLOCK)
#fuses INTRC,NOWDT,NOPROTECT,PUT,NOLVP

// General IO Pin Definitions
#define LED               PIN_A0   // The LED
#define LEDIRQ            PIN_A1
#define I2CSDA            PIN_B1   // I2C SDA pin
#define I2CSCL            PIN_B4   // I2C SCL pin
#define RS232HOSTPCXMIT   PIN_A2   // XMIT pin to host PC
#define RS232HOSTPCRCV   PIN_A3   // RCV pin from host PC

// IO Pin State Definitions
#define LED_ON output_high(LED)
#define LED_OFF output_low(LED)

#use rs232(baud=1200, xmit=RS232HOSTPCXMIT, rcv=RS232HOSTPCRCV, stream=HOSTPC)
neil



Joined: 08 Sep 2003
Posts: 128

View user's profile Send private message

Thanks Kyle
PostPosted: Thu Jan 22, 2004 5:29 am     Reply with quote

Hi Kyle, thanks for your suggestion. My code was working and returning the correct data, but my 'error' LED was coming on (triggered by the 'default' state in the state machine. As it happens, this default was triggered because of the stop state being ignored.
I put your if statement around the state machine, which I think is a neat way of doing it as it prevents the other states being checked if a 'stop' was received, keeping the ISR small on this occasion. I can't see a reason for this being a bad idea. Anyone?

The real reason for my slave not working was a hardware 'oversight'. I had read (I think on Philips datasheets) that SCL only needed to be bidirectional in a multi-master environment. I had to optoisolate the I²C bus, so made SDA bidir, but not SCL, resulting in the slave being incapable of clock stretching! This was a stupid mistake as I knew about this when I wrote the state machine, but didn't twig that this was impossible. So - a big Homer Simpson "D'oh" Embarassed Embarassed Embarassed Embarassed

Finally, I am going to put in a timeout as the errata suggested. It could be catastrophic if the thing was to hang (at least for any significant time). This slave will be receiving 'demand' data from a control system which regulates the current to an RF power tube filament.
If it was to put on full power too suddenly on a cold filament, blowing the filament would cost £40,000. If it was to trip off, our RF systems would fail, and as our 'business' is a synchrotron, producing neutrons for the science research community, having beam downtime will cost around £100,000 per hour! - No pressure then!

I'm amazed that they've let me loose on it!!!! Surprised

Thanks for all the help, Mark, Kyle, Kenny and 'guests'
No doubt you will hear from me again!
Neil.
neil



Joined: 08 Sep 2003
Posts: 128

View user's profile Send private message

Back for more!
PostPosted: Fri Jan 23, 2004 5:13 am     Reply with quote

Hi Mark/Kyle!

Mark may remember helping me on the Thyristor trigger code, using the EXT isr for zero crossing and the CCP isr for the triggering delay. This I²C slave is to receive a 'phase angle' word for the thyristor trigger. My slave code now works quite well, but with both together (3 interrupt sources) problems are occuring when they happen to coincide. I am seeing a flicker on the bulb I have as the thyristor load every so often. I can't allow this to happen as it will eventually be driving a 6KVA transformer! I am also seeing the slave miss data every so often which I think is because the SSP interrupt is being missed when the processor happens to be handling one of the other two.

Do you have any ideas for a way around this?!

My slave code is a bit different in the way it writes back to the master. I wrote it in the same way as AN734, where the collision flag is tested as the SSPBUF is written to. I also have a tight while loop testing the BF bit, so it sits doing nothing while BF is true. Not a good idea to have in an ISR, I know! I am now trying it without the tests to see if the slave no longer hangs. (It was hanging after several minutes of good activity).

My write function below is called from the states in the ISR which require Slave to Master write:
Code:
void write_i2c(){
   SSPOV=0;
   while(BF); // If buffer is full, wait to clear.
   do{
      WCOL=0;  // Clear a previous collision flag.
      SSPBUF=RX_buff[out_ptr];
      }while(WCOL);
   out_ptr++;
   out_ptr &= 15;
   CKP=1;            // Release clock to initiate transmit.
   }
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Fri Jan 23, 2004 7:22 am     Reply with quote

Try doing it this way and see what happens.
Code:

void write_i2c(){
  SSPBUF=RX_buff[out_ptr];
  out_ptr++;
  out_ptr &= 15;
  CKP=1;            // Release clock to initiate transmit.
}


What speed are you running at? I have 16F876 running at 20MHz controlling 6 Triacs @ 60Hz with no flickers and 7 interrupt sources running. So what you are trying to do should be possible. If you want me to take a look at your isr's you can post them or send them to me.
neil



Joined: 08 Sep 2003
Posts: 128

View user's profile Send private message

done it
PostPosted: Fri Jan 23, 2004 7:49 am     Reply with quote

Hi, I did exactly that shortly after my last post and have had it running a couple of hours. The slave occasionally missed data, but it never locked up. - Take note Guy, you will need to change this in the code you asked me for!

I am running at 4MHz. Note that as well as you having 7 interrupts running, your zero crossing is faster than over here!

I will send you my complete code by email. Can you please comment on my code layout and structure. I am 'doing it my way' and picking up what I hope to be 'good habits' from this forum, but I could do with someone else's opinion. I won't be offended if you tell me it's crap! Smile
Regards,
Neil.
GDetienne



Joined: 20 Sep 2003
Posts: 47
Location: Brussel - Belgium

View user's profile Send private message

Thanks
PostPosted: Fri Jan 23, 2004 8:28 am     Reply with quote

Thanks neil, I try it and I send a mail if I have questions.
Have a nice week end. Very Happy
neil



Joined: 08 Sep 2003
Posts: 128

View user's profile Send private message

More questions of a different variety!
PostPosted: Tue Jan 27, 2004 8:27 am     Reply with quote

Hello again,
This time I have a question relating to interrupts, for those who know the ins and outs of CCS's handler better than I do.

I am still having problems with my I²C slave missing some of the data transactions and I am pretty sure it is because the other 2 interrupts are periodically coinciding and blocking the SSP ISR from being serviced. My Ext and CCP ISRs are not likely to overlap, as they are synchronised to each other with a variable delay between. Eg. The EXT int resets Timer1 and some time after, CCP fires.

Is there a good way of ensuring that the SSP int is never missed? Could I poll for the SSPIF inside the other interrupts and jump to the SSP handler?

Thanks in advance,
Neil.
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Tue Jan 27, 2004 11:22 am     Reply with quote

If they do coincide you should get back to back ints so polling should not be necessary. Do you actually miss the data or does the master stop transmitting.
neil



Joined: 08 Sep 2003
Posts: 128

View user's profile Send private message

Ints
PostPosted: Wed Jan 28, 2004 3:17 am     Reply with quote

Hi Mark, the slave is writing back the previous data which was written to it. This happens repeatedly (10-15 times) where it seems to be ignoring new data being sent. Eventually this clears and the new data is echoed back. This doesn't appear to be particularly periodic which is what made me think it was the interrupts drifting in and out of time with each other.
neil



Joined: 08 Sep 2003
Posts: 128

View user's profile Send private message

Example
PostPosted: Wed Jan 28, 2004 3:22 am     Reply with quote

Here is a snip from the terminal showing what the slave is doing. 'Command' is what I am typing, it is captured in a gets(), then atol() on the master board and sent over I²C. The 'Echo' is the reply from slave to master and should follow command.

Command: 1000 Echo: 1000\0A
Command: 2000 Echo: 2000\0A\0D
Command: 3000 Echo: 3000\0A\0D
Command: 4000 Echo: 3000\0A\0D
Command: 5000 Echo: 5000\0A\0D
Command: 6000 Echo: 5000\0A\0D
Command: 7000 Echo: 7000\0A\0D
Command: 8000 Echo: 7000\0A\0D
Command: 9000 Echo: 7000\0A\0D
Command: 9500 Echo: 7000\0A\0D
Command: 0 Echo: 7000\0A\0D
Command: 0 Echo: 7000\0A\0D
Command: 0 Echo: 7000\0A\0D
Command: 0 Echo: 7000\0A\0D
Command: 0 Echo: 7000\0A\0D
Command: 0 Echo: 0\0A \0D
\0D
kda406



Joined: 17 Sep 2003
Posts: 97
Location: Atlanta, GA, USA

View user's profile Send private message

Clock stretching
PostPosted: Wed Jan 28, 2004 8:47 am     Reply with quote

Hi guys. At this point in the thread, I may be off topic and I apologize if this is not helpful, but I think some users may find this useful. After posting my edit of Kenny's AN734 code, I started beginning implementation in a real product. The code I posted previously mysteriously stopped working. I finally determined it was a timing issue. I'll get to the fix in a minute.

"State 0x30"
During my discovery process, I tried speeding up my 16F818, which did not solve the problem. I also tried a 16F819 which showed the same symptoms. I re-reviewed the MicroChip I2C slave errata and decided to try a different chip that was not affected by the 'slave bug'. So I rewired my circuit to use a 16F872, which had the same timing problem. The reason I am telling you about all of the chips I tried is because all 3, infrequently experienced state 0x30, which is not part of the MicroChip AN734 spec, but was part of my posted edit. I don't know why sometimes the stop bit causes SSPIF to trip an interrupt, but it appears to happen outside of those chips listed in the errata, so I suggest having a handler for this state to anyone writing I2C slave code.

"Timing"
After I started using the 16F872 I clocked it faster and faster trying to alleviate the timing issue. With the master running at only 4 MHz, I sped the slave all the way up to 14.7 MHz and still could not process the interrupts fast enough. Kenny had just added clock stretching to his AN734 port right before I modified it and posted it and I could not figure out why it was not working. Well it was, but it was working too late. If you review my editted code post, you'll see that inside of each case in the ISR, the clock is stretched. But for my production program, I had a few lines of "overhead" code that had to be taken care of before the switch to the appropriate state handler. Between the tiny bit of overhead and the switch code itself, the master was overrunning the slave.

Since each case in the ISR strecthed the clock anyway, what I found that solved my timing problem was to move the clock stretching to the first and last thing that were taken care of in the ISR like so:
Code:
// I2C Slave Interrupt Handler
#int_SSP
SSP_isr() {
   CKP = 0;   // Make Master wait by holding SCL low
<overhead and switch/case code here>
   CKP = 1;       // Allow master to continue by re-enabling SCL
}


This allowed me to slow the slave back down. Today I plan to go back to the 16F818 running on its internal RC. I believe stretching the clock in this manner should allow the slave to run really slow. I'll repost if there are any significant developments on that front.

Neil, stopping the clock like this might help with your conflicting ISRs too. I am not that familiar with your code. But I think that if you get called by your CCP interrupt during the processing of the I2C interrupt it will be okay because the I2C bus would simply wait for the CCP to be serviced, and for the I2C to finish before clocking again. I make no guarantees (esp at $147K/hr), but it may help. Very Happy

-Kyle
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Wed Jan 28, 2004 9:00 am     Reply with quote

Hi Neil,

Post your slave isr code or send it to me. I believe that you said you changed it in respect to the buffer size. It looks as though it is working except that the wrong data is being transmitted back. This sounds like a pointer not being set right rather than missing ints.
neil



Joined: 08 Sep 2003
Posts: 128

View user's profile Send private message

Cheers Kyle
PostPosted: Wed Jan 28, 2004 9:05 am     Reply with quote

Thanks for that!

I won't be commissioning the thing just yet! Laughing
I did wonder about stretching the clock at the beginning and end of the ISR, but it surely shouldn't need it? In my code (adding bits suggested by Kenny) I put in clock stretching at each state. This I would have thought has the same effect, but takes up (wastes) more cycles?

My EXT and CCP interrupts have the same period, but there is a variable delay between them. This is because EXT int is clearing timer1, and CCP fires some known time after (Thyristor triggering)

I will try what you suggest and get back soon.
_________________________________________________________

I have had a few people contacting me by email and private message about this topic, and asking me lots of questions on how to implement this slave Rolling Eyes shudder! I'm not the best person to ask!!

It would be best if those people post to this (already long) thread, so we can all contribute.
Smile
neil



Joined: 08 Sep 2003
Posts: 128

View user's profile Send private message

Code snip
PostPosted: Wed Jan 28, 2004 9:49 am     Reply with quote

Hi Mark, I changed the buffer to 2 bytes, so it's no longer really a buffer. I'm just using a 2 byte array to hold the 2 incoming bytes.
Code:
case 0b00101001:     // Write mode (Master to Slave), last byte was data.
      SSPOV=0;
      CKP=0;
      rx_buff.bytes[in_ptr++]=SSPBUF; // Read bytes into buffer.
      if(in_ptr==2) bytes_in=1; // A flag to say both bytes are RX.
      in_ptr &= 1;     // Roll around pointer, back to 0
      CKP=1;
      break;

RX_buff is now a union. Eg.
Code:
union buffers{
   int bytes[2];
   long words;
   }RX_buff;
to easily convert between bytes and words.

My write_i2c() routine is now:
Code:
void write_i2c(){
      SSPBUF=RX_buff.bytes[out_ptr++];
      out_ptr &= 1;
      CKP=1;
      }
This sometimes works several times in a row, then fails (as in the terminal snippet earlier). Occasionally I have also seen what appears to be both master and slave stop responding, contrary to what I thought the other day. Sad

Can I really be that bad at programming?! Crying or Very sad

_____________________________________________
I say I am not a professional programmer... My line manager tells me "I am, because I am being paid to program"
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2
Page 2 of 2

 
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