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 CCS Technical Support

32bit SPI transfers using PIC16F1513?

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



Joined: 04 Apr 2018
Posts: 13

View user's profile Send private message

32bit SPI transfers using PIC16F1513?
PostPosted: Tue May 01, 2018 11:16 am     Reply with quote

I am trying to talk to a MAX30003 ECG chip via the SPI but the MAX30003 has a 32bit SPI read/write cycle. The 16F1513 seems rather intent on an 8bit cycle, but I may just be ignorant of a way around this.

The MAX30003 appears to reset the state machine on every assertion of chip select, which happens on 8bit boundaries, so the DO of the MAX30003 is always zero.

I have tried to fool the processor, telling it the wrong pin for chip select and manually controlling the real chip select pin, but when I do that, the PIC doesn't generate the SClk.

So, my question to the greater knowledge is - is there a way to get the 16F1513 to perform a 32bit SPI transfer? I see hints of 32bit transfer versions of the spi_xfer routine, but don't know whether these are available on the 8bit PICs.

Failing a 32bit transfer, can someone please tell me how to set up a single chip select cycle for four 8bit transfers?

Here's what I have so far:

Code:

#include <uart.h>
//  Now trying to spoof the PIC - tell it enable is on A2, and control C2 manually.
#use spi (MASTER, CLK=PIN_C3, DI=PIN_C4, DO=PIN_C5, ENABLE=PIN_C2, BAUD=500000, MODE=3, BITS=8, STREAM=MAX30003_SPI)

#include "MAX30003.h"
#use fast_io(A)
#use fast_IO(B)
#use fast_IO(C)

int32 chip_status;

void main()
{
  setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1|RTCC_8_BIT);
  spi_init( MAX30003_SPI, 500000);


//  set_tris_c( 0xFB);  // With set_tris_c, there is no clock. Without
                                //  set_tris_c, there is a clock.
  while(TRUE)
  {

    chip_status = MAX30003_ReadReg( MNGR_DYN);      //  s/b 0x3f0000
   
    delay_us( 250);
   
  }
}

/**
  ******************************************************************************
  * @file MAX30003.c
  * @brief Code for the MAX30003 ECG chip
  * @author John Griswold
  ******************************************************************************
  *
  *
  * COPYRIGHT( C )2018 Vivonics,Inc.
  *
  */
/**
  * @brief Enable the Max chip by lowering its Chip Select line
  * @param None
  * @retval None
  */
void MAX30003_ChipSelect( void)
{
  output_low( MAX30003_CS);
  delay_us( 500 );
}

/**
  * @brief Disable the Max chip by raising its Chip Select line
  * @param None
  * @retval None
*/
void MAX30003_ChipDeselect(void)
{
  output_high( MAX30003_CS);
  delay_us( 500);
}

/**
  * @brief Read 32-bit data from register
  * @param Addr register address
  * @retval 24-bit data read in a 32-bit word
  * @note - MAX30003 spec says the data on a read is a don't-care
  *       so I used 0x00.
  */
unsigned int32 MAX30003_ReadReg(unsigned int8 addr)
{
  int32 data = 0;
  int8 ReadData;
  int32 outdata = ((addr | RREG30003) << 24);
  MAX30003_ChipSelect( );
 
  spi_xfer( addr | RREG30003); //Send register location


  ReadData = spi_xfer( MAX30003_SPI,0xFF );//Read Data
  data |= ReadData; //  bits 23..16
  ReadData = spi_xfer( MAX30003_SPI,0xFF );//Read Data
  data <<= 8;
  data |= ReadData; //  bits 15..8
  ReadData = spi_xfer( MAX30003_SPI,0xFF );//Read Data
  data <<= 8;       
  data |= ReadData; //  bits 7..0

  MAX30003_ChipDeselect( );
  return data;
}
.
.
.




Oh, and when I tell the #use SPI that enable is on C2, and manually lower and raise C2 to effect a 32bit transfer, the PIC deasserts and asserts chip select on C2 anyway. This just confuses the bejesus out of the MAX30003 state machine.

Thanks,
John
_________________
John Griswold KK1X
High Tech Migrant Worker
Ttelmah



Joined: 11 Mar 2010
Posts: 19562

View user's profile Send private message

PostPosted: Tue May 01, 2018 2:14 pm     Reply with quote

Two choices.
1) Remove the enable from #USE_SPI.
You can then operate the CS yourself.

2) However you can set the #USE to do 32bit transfers, but you then need to tell the xfer command to do 32bit transfers.
Understand if you call:
Code:

OutData = spi_xfer( MAX30003_SPI,0xFFFFFFFF,32 ); //This will do a 32bit transfer
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

Re: 32bit SPI transfers using PIC16F1513?
PostPosted: Tue May 01, 2018 3:42 pm     Reply with quote

johngriswold wrote:

#use spi (MASTER, CLK=PIN_C3, DI=PIN_C4, DO=PIN_C5, ENABLE=PIN_C2, BAUD=500000, MODE=3, BITS=8, STREAM=MAX30003_SPI)


// set_tris_c( 0xFB); // With set_tris_c, there is no clock.

The reason is because your TRIS value is wrong. In binary, it's:
Code:
1111 1011

The PIC data sheet says:
Quote:

• SDI must have corresponding TRIS bit set
• SDO must have corresponding TRIS bit cleared (= output)
• SCK (Master mode) must have corresponding TRIS bit cleared (= output)

SCLK, SDO, and Enable all need to be set as output pins. Your TRIS
statement only sets pin C2 as an output. That's why it didn't work.

But in CCS, their functions will automatically set the correct TRIS
for any pins used by the function. This will not be done if you
specify #fast_io() mode for the i/o port.
johngriswold



Joined: 04 Apr 2018
Posts: 13

View user's profile Send private message

PostPosted: Wed May 02, 2018 8:29 am     Reply with quote

Thanks to you both. I'm closer now.

Yeah, the set_tris_c() was kind of dumb on my part. I assumed that the #use SPI statement would initialize things. I was wrong!

Now I get proper chip select without having to manually control it, the clock seems OK, data out from the PIC seems OK (I need to look a bit more closely) but the data in doesn't seem right - but that might be the slave chip.

The code (with corrected set_tris_c(), PIC-generated chip select, and 32-bit #use and transfers) now looks like:

Code:

#include <uart.h>
//  Now trying to configure the PIC for 32-bit SPI
#use spi (MASTER, CLK=PIN_C3, DI=PIN_C4, DO=PIN_C5, ENABLE=PIN_C2, BAUD=500000, MODE=3, BITS=32, STREAM=MAX30003_SPI)

#include "MAX30003.h"

int32 chip_status;

void main()
{
//  setup_adc_ports(sAN0|sAN1);
//  setup_adc(ADC_CLOCK_INTERNAL);
  setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1|RTCC_8_BIT);
  spi_init( MAX30003_SPI, 500000);

  //  Port C - clock on C3, DI on C4, DO on C5, enable on C2
  //  76543210
  //  IIOIOOII == D3 (DOH!)
  set_tris_c( 0xD3);

  while(TRUE)
  {
    chip_status = MAX30003_ReadReg( MNGR_DYN);      //  s/b 0x3f0000
   
    delay_us( 250);

  }
}

/**
  ******************************************************************************
  * @file MAX30003.c
  * @brief Code for the MAX30003 ECG chip
  * @author John Griswold
  ******************************************************************************
  *
  *
  * COPYRIGHT( C )2018 Vivonics,Inc.
  *
  */
/**
  * @brief Enable the Max chip by lowering its Chip Select line
  * @param None
  * @retval None
  * @note Notice the in - built time delay so no need to wait after
  * chipselect assertion
  */
void MAX30003_ChipSelect( void)
{
//  output_low( MAX30003_CS);
//  delay_us( 500 );
}

/**
  * @brief Disable the Max chip by raising its Chip Select line
  * @param None
  * @retval None
  * @note Notice the in-built time delay so no need to wait before
  *       chipselect deassertion
*/
void MAX30003_ChipDeselect(void)
{
//  output_high( MAX30003_CS);
//  delay_us( 500);
}

/**
  * @brief Write 32-bit data to a register via SPI
  * @param Addr-register address
  * @param Data-32-bit data
  * @retval None-no data is returned
  */
void MAX30003_WriteReg(unsigned int8 addr,unsigned int32 data)
{
  MAX30003_ChipSelect( );
  data |= addr << 24;
 
  spi_xfer( MAX30003_SPI, data, 32 );
 
  MAX30003_ChipDeselect( );
}
/**
  * @brief Read 32-bit data from register
  * @param Addr register address
  * @retval 24-bit data read in a 32-bit word
  * @note - MAX30003 spec says the data on a read is a don't-care
  *       so I used 0x00.
  */
unsigned int32 MAX30003_ReadReg(unsigned int8 addr)
{
  int32 data = 0;
  int8 ReadData;
  int32 outdata = ((addr | RREG30003) << 24);
  MAX30003_ChipSelect( );
  data = spi_xfer( MAX30003_SPI, outdata, 32);
 
  MAX30003_ChipDeselect( );
  return data;
}


_________________
John Griswold KK1X
High Tech Migrant Worker
temtronic



Joined: 01 Jul 2010
Posts: 9253
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed May 02, 2018 9:51 am     Reply with quote

I've always thought (right or wrong) that it's best NOT to use fast_io() and set_tris() during the 'R&D' phase of the project. Like WDT, you can get into a hornet's nest of problems YOU create by not letting the compler 'do the dirty work'. I think (again right or wrong) that if the compiler sees you using them, it may modify the USE ??? to ignore their 'internal' settings and let you fail...
I've been bit a couple of times in 25 years of using fastio() and only 2 or 3 projects actually needed it, for speed.

just food for thought.
johngriswold



Joined: 04 Apr 2018
Posts: 13

View user's profile Send private message

PostPosted: Wed May 02, 2018 10:23 am     Reply with quote

Indeed - I took out the set_tris_c() statement altogether, and I get the same results - still get chip select and clock, data out to the slave looks good, but the slave returns only 1's, which, like so many things, puzzles me.

Thanks for the tip, temtronic.
_________________
John Griswold KK1X
High Tech Migrant Worker
Ttelmah



Joined: 11 Mar 2010
Posts: 19562

View user's profile Send private message

PostPosted: Wed May 02, 2018 11:09 am     Reply with quote

Are you sure about mode=3?. Looking at the data sheet mode=0 looks more correct.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed May 02, 2018 11:51 am     Reply with quote

Quote:
but the slave returns only 1's

Post both of your current driver files, Max30003.c and Max30003.h.

Also post a list of connections between your PIC and the Max30003.
I want to make sure that you have:

PIC Max30003
SDO to SDI
SDI to SDO
SCLK to SCLK
CS to CSB

A common mistake is connecting SDO to SDO, and SDI to SDI.
newguy



Joined: 24 Jun 2004
Posts: 1911

View user's profile Send private message

PostPosted: Wed May 02, 2018 12:12 pm     Reply with quote

PCM programmer wrote:
Also post a list of connections between your PIC and the Max30003.
I want to make sure that you have:

PIC Max30003
SDO to SDI
SDI to SDO
SCLK to SCLK
CS to CSB

A common mistake is connecting SDO to SDO, and SDI to SDI.


Pet peeve of mine, that's why I always name my pins MOSI and MISO. Master Out Slave In and Master In Slave Out. No ambiguity.
johngriswold



Joined: 04 Apr 2018
Posts: 13

View user's profile Send private message

PostPosted: Wed May 02, 2018 12:16 pm     Reply with quote

I'm not sure about mode=3. In fact, after changing to mode 0, I seem to be getting data back from the MAX30003.

I am sure about the connections, which are correct. I have an EE to beat up on for this Smile

The file MAX30003.c is incorporated in the main c file. I ran into a problem a few weeks back causing Microchip support to suggest I not use multiple compilation units. Seriously.

Here is the header file:
Code:

/**
  ******************************************************************************
  * @file       MAX30003.h
  * @brief      Register definitions for MAX30003 ECG chip
  * @author      John Griswold
  ******************************************************************************
  *
  *
  * COPYRIGHT(C) 2018 Vivonics, Inc.
  *
  */

#ifndef MAX30003_H_
#define MAX30003_H_
#define BIT(X) 1<<(X)

/**
  * @brief    Bit definitions for MAX30003 ECG chip
  */
/**
  * Write and Read control
  */
#define  WREG30003         0x00
#define  RREG30003         0x01

/**
  * @note - Register addressing for MAX30003 requires shifting the stated address
  *         one bit left, and ORing in the Read/-Write bit. Do the shifting here
  *         so it doesn't have to be done for each operation at run time.
  */
 
#define   NO_OP           0x00 << 1
/**
  * @brief  Status register
  * @note   Oddly populated, this register uses 23:20, 11:8, and 3:0
  */
#define   STATUS          0x01 << 1
#define   EINT          BIT(23)
#define   EOVF          BIT(22)
#define   FSTINT        BIT(21)
#define   DCLOFFINT     BIT(20)
#define   LONINT        BIT(11)
#define   RRINT         BIT(10)
#define   SAMP          BIT(9)
#define   PLLINT        BIT(8)
#define   LDOFF_PH      BIT(3)
#define   LDOFF_PL      BIT(2)
#define   LDOFF_NH      BIT(1)
#define   LDOFF_NL      BIT(0)

/**
  * @brief  Interrupt Enable register
  */
#define   EN_INT          0x02 << 1
#define   EN_EINT         BIT(23)
#define   EN_EOVF         BIT(22)
#define   EN_FSTINT       BIT(21)
#define   EN_DCLOFFINT    BIT(20)
#define   EN_LONINT       BIT(11)
#define   EN_RRINT        BIT(10)
#define   EN_SAMP         BIT(9)
#define   EN_PLLINT       BIT(8)
#define   INTB_TYPE       BIT(1)|BIT(0)
#define   DISABLE         0
#define   CMOS_DRIVER     1
#define   NMOS_DRIVER     2
#define   OD_NMOS_DRIVER  3

/**
  * @brief  Interrupt Enable register 2
  * @note - appears to be the same as EN_INT, which strikes me as very odd.
  */
#define   EN_INT2         0x03 << 1
/**
  * @brief   
  * @note   
  */
#define   MNGR_INT        0x04 << 1
/**
  * @brief    Manage operation of configurable interrupt buts for ECG FIFO
  * @note   
  */
#define   EFIT            0xF000
#define   CLR_FAST        BIT(6)
#define   CLR_RRINT       BIT(5)|BIT(4)
#define   CLR_SAMP        BIT(2)
#define   SAMP_IT         BIT(1)|BIT(0)
/**
  * @brief    Dynamic mode management
  * @note   
  */
#define   MNGR_DYN        0x05 << 1
#define   FAST            BIT(23)|BIT(22)
#define   FAST_TH         BIT(21)|BIT(20)|BIT(19)|BIT(18)|BIT(17)|BIT(16)
/**
  * @brief    Software Reset
  * @note     Resets device after SPI write cycle - value 0
  */
#define   SW_RST          0x08 << 1

/**
  * @brief    Resynchs the device after reconfiguration
  * @note     Write a zero
  */
#define   SYNCH           0x09 << 1
/**
  * @brief    Reset the FIFO (e.g. after a FIFO overflow)
  * @note     Write a zero
  */
#define   FIFO_RST        0x0A << 1
/**
  * @brief    Chip revision and ID information
  * @note   
  */
#define   INFO            0x0F << 1
/**
  * @brief    General configuration register
  * @note   
  */
#define   CNFG_GEN        0x10 << 1
#define   EN_ULP_LON      BIT(23)|BIT(22)
#define   FMSTR           BIT(21)|BIT(20)
#define   EN_ECG          BIT(19)
#define   EN_DCLOFF       BIT(13)|BIT(12)
#define   IPOL            BIT(1)
#define   IMAG            BIT(10)|BIT(9)|BIT(8)
#define   VTH             BIT(7)|BIT(6)
#define   EN_RBIAS        BIT(3)|BIT(2)
#define   RBIASP          BIT(1)
#define   RBIASN          BIT(0)
/**
  * @brief    Configure operation of Internal calibration voltage sources
  * @note   
  */
#define CNFG_CAL          0x12 << 1
#define EN_VCAL           BIT(22)
#define VMODE             BIT(21)
#define VMAG              BIT(20)
#define FCAL              BIT(14)|BIT(13)|BIT(12)|BIT(11)
#define FIFTY             BIT(10)
#define THIGH             BIT(9)|BIT(8)|BIT(7)|BIT(6)|BIT(5)|BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0)
/**
  * @brief    Configure input mux
  * @note   
  */
#define   CNFG_EMUX       0x14 << 1
#define   POL             BIT(23)
#define   OPENP           BIT(21)
#define   OPENN           BIT(20)
#define   CALP_SEL        BIT(19)|BIT(18)
#define   CALN_SEL        BIT(17)|BIT(16)
/**
  * @brief    Configure ECG channel
  * @note   
  */
#define   CNFG_ECG        0x15 << 1
#define   RATE            BIT(23)|BIT(22)
#define   ECG_GAIN        BIT(17)|BIT(16)
#define   DHPF            BIT(14)
#define   DLPF            BIT(13)|BIT(12)
/**
  * @brief    Configure heart rate detection block
  * @note     
  */
#define   CNFG_RTOR1      0x1D << 1
#define   WNDW            BIT(23)|BIT(22)|BIT(21)|BIT(20)
#define   GAIN            BIT(19)|BIT(18)|BIT(17)|BIT(16)
#define   EN_RTOR         BIT(15)
#define   PAVG            BIT(13)|BIT(12)
#define   PTSF            BIT(11)|BIT(10)|BIT(9)|BIT(8)
/**
  * @brief   
  * @note   
  */
#define   CNFG_RTOR2      0x1E << 1
#define   HOFF            BIT(21)|BIT(20)|BIT(19)|BIT(18)|BIT(17)|BIT(16)
#define   RAVG            BIT(13)|BIT(12)
#define   RHSF            BIT(10)|BIT(9)|BIT(8)
/**
  * @brief    ECG Burst and ECG data
  * @note     Registers use the same bitmasks
  */
#define   ECG_FIFO_BURST  0x20 << 1
#define   ECG_FIFO        0x21 << 1
#define   ECG_SAMPLE      0x00FFFFC0
#define   ETAG            BIT(5)|BIT(4)|BIT(3)
#define   PTAG            BIT(2)|BIT(1)|BIT(0)
/**
  * @brief    RTOR Interval register
  * @note   
  */
#define   RTOR            0x25 << 1
#define   RTOR_MASK       BIT(23)|BIT(22)|BIT(21)|BIT(20)|BIT(19)|BIT(18)|BIT(17)|BIT(16)|BIT(15)|BIT(14)|BIT(13)|BIT(12)|BIT(11)|BIT(10)
#define   NO_OP0          0x7F << 1


void MAX30003_WriteReg( unsigned int8 addr, unsigned int32 data);
unsigned int32 MAX30003_ReadReg( unsigned int8 addr);
void MAX30003_Reset( void);
void MAX30003_Synch( void);
void MAX30003_Initialize( void);
void MAX30003_ChipSelect( void);
void MAX30003_ChipDeselect( void);
void MAX30003_EnableInterrupts( void);
void MAX30003_DisableInterrupts( void);
void MAX30003_ResetFIFO( void);

#define MAX30003_CS PIN_C2
#define MAX30003_CS_ON  0
#define MAX30003_CS_OFF 1
#endif   // MAX30003_H_


So, this looks like some progress.

Thank you all so much. I'll very likely be back!
Very Happy
_________________
John Griswold KK1X
High Tech Migrant Worker
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed May 02, 2018 4:16 pm     Reply with quote

johngriswold wrote:

The file MAX30003.c is incorporated in the main c file. I ran into a
problem a few weeks back causing Microchip support to suggest I not use
multiple compilation units.

Multiple compilation units are quite different than having your driver files
in separate files.

Method 1:
The standard way to use CCS is to put your driver code in separate files.
Then use #include lines in your main C file to include them in the program.
So in your main.c, you should have:
Code:

#include "MAX30003.c" 

This is the way that nearly all of us do it.


Method 2:
When using Multiple Compilation Units, individual files can be compiled
separately and then linked together later. This is what Microchip support
recommended that you don't do. This FAQ article explains how to use MCUs:
https://www.ccsinfo.com/faq.php?page=multi_comp_units
Most of us don't use MCUs.


Method 3:
This is what you said you are doing. Combine all driver files with the
main.c file. Don't use #include statements. Just have one big file.
This is not normally done.
Ttelmah



Joined: 11 Mar 2010
Posts: 19562

View user's profile Send private message

PostPosted: Thu May 03, 2018 1:37 am     Reply with quote

johngriswold wrote:
I'm not sure about mode=3. In fact, after changing to mode 0, I seem to be getting data back from the MAX30003.


OK. Well that sounds more hopeful. Smile

The timing diagrams show data being sampled for both transmission and reception on the rising edge of the clock, with data stable around this point. This is mode 0, hence my suggestion.
Question now is whether the data has any resemblance to what you expect?.

Do something basic, like setting a register to some specific value, and then read this back. You need to be getting back exactly what you have written before trying to do anything more complex.
johngriswold



Joined: 04 Apr 2018
Posts: 13

View user's profile Send private message

PostPosted: Thu May 03, 2018 7:02 am     Reply with quote

Ttelmah - I anticipate read/write tests today.

PCMProgrammer - I am not in the habit of combining all of the files into one - I was just following the suggestions of the compiler vendor. By putting all of the code into one file (rather than #include), I had hoped to make it somewhat more convenient for folks in this forum to view my code.

Thank you all for your help. You rock!
_________________
John Griswold KK1X
High Tech Migrant Worker
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Thu May 03, 2018 9:18 am     Reply with quote

With many SPI devices, for example memories, there is no fixed transfer length as there can be with things like ADCs and DACs. Also with multiple devices on one SPI port it's not so easy to deal with the mulitple selects: you would have to have multiple #use spi directives and stream names.

So, for many SPI situations its not great or even practical to specify enable in the #use spi. Instead, while you sound like you think it's "cheating" - you use the terms "spoofing" and "fooling the processor" (you're not, of course, the processor has nothing to do with it) - it's normal practice to use normal I/O bits for the select and control them in user code, with as many byte transfers as you need between enabling and disabling the device. This is the way I normally use SPI.

When you are using a device like a DAC, where all transfers are the same length, say 24 bits: three bytes, you can set up the SPI to so just that. The SPI peripheral hardware, if used, doesn't do the enable, instead the compiler will provide code to wrap the transfer, of as many bytes as required, to enable/select the device being talked to. If think if you do not specify a binary power for the number of bits, it cannot use the SPI hardware and implements a software emulation instead. Generally, though by no means all, devices that require a non-binary number of bits will often allow extra dummy bits at the end, allowing the next higher binary power number of bits to be used.

Personally, I'm so used to doing my own chip enables and to transferring byte-by-byte that that's what I always use, but that's essentially just habit.
johngriswold



Joined: 04 Apr 2018
Posts: 13

View user's profile Send private message

PostPosted: Thu May 03, 2018 9:27 am     Reply with quote

Yeah, I know I wasn't fooling the processor... Fortunately for me, there is only one SPI device in this project, and thanks to the kind folks in this forum, I'm actually writing and reading the chip over SPI. I found that the straightforward(?) use of this works just fine:
Code:
#use spi (MASTER, CLK=PIN_C3, DI=PIN_C4, DO=PIN_C5, ENABLE=PIN_C2, BAUD=SPI_BAUD, MODE=0, BITS=32, STREAM=MAX30003_SPI)

(SPI_BAUD is defined as 1000000)

Thank you for your input as well, RF. I'll tuck this away in my little pea brain for the next project.
_________________
John Griswold KK1X
High Tech Migrant Worker
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