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

1-Wire Search ROM

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



Joined: 24 Feb 2010
Posts: 22

View user's profile Send private message

1-Wire Search ROM
PostPosted: Tue Apr 06, 2010 3:04 am     Reply with quote

Hi all,

If anyone can help me with this problem, I will appreciate it a lot!

I am using a PIC24HJ128GP502 with a 20MHz clock and I am trying to interface with a DS18B20 temperature sensor. At the moment I am able to get a result from a single temp sensor, but I would like to interface with more than one at a time.

My problem is that when I implement the SEARCH ROM function and try to find devices, my UART continuously outputs 0xFF, even though I don't call printf... This is quite strange.

I tried to implement the SEARCH ROM function myself, but after a while gave up and used the code cotestatnt put in the code library. But alas, I still have the same problem.

Here is my code, with the code from cotestatnt:

one_wire.c
Code:
#ifndef ONE_WIRE_C
#define ONE_WIRE_C

#define OW_PIN PIN_A4

// Global variables
int8 RomBytes[8];     
int8 lastDiscrep = 0;
short doneFlag = 0;
int8 FoundROM[9][8];    // Table of found ROM codes, 8 bytes for each
int8 numROMs;
int8 dowcrc;            // crc is accumulated in this variable

/*   OWWriteBit()
 *   Description:
 *      Writes a single bit on the 1-Wire bus
 *   Returns:
 *      Nothing
 */
void OWWriteBit(int8 bitval)
{
   if (bitval)
   {
      //Write '1' bit
      output_low(OW_PIN);
      delay_us(6);
      output_float(OW_PIN);
      delay_us(64);
   }
   else
   {
      //Write '0' bit
      output_low(OW_PIN);
      delay_us(60);
      output_float(OW_PIN);
      delay_us(10);
   }   
}

/*   OWReadBit()
 *   Description:
 *      Reads a single bit from the 1-Wire bus
 *   Returns:
 *      The result from the read
 */
int8 OWReadBit(void)
{
   int8 value;
   
   output_low(OW_PIN);
   delay_us(6);
   output_float(OW_PIN);
   delay_us(9);
   value = input(OW_PIN);
   delay_us(55);
   
   return value;
}      

/*   OWReset()
 *   Description:
 *      Reset the 1-Wire bus slave devices and ready them for a command
 *   Returns:
 *      0 = Device(s) present
 *      1 = No device present
 */
int1 OWReset(void)
{
   int1 value = 0;
   
   output_low(OW_PIN);
   delay_us(480);         //Pull wire LOW for minimum of 480us
   output_float(OW_PIN);   //Let the line recover to its HIGH state
   delay_us(80);         //Wait for the device to transmit its presence
   value = input(OW_PIN);   //Receive device present signal
   delay_us(400);         //Complete the reset time slot
   
   return value;
}

/*   OWWriteByte()
 *   Description:
 *      Write a byte of data to the 1-Wire slaves
 *   Returns:
 *      Nothing
 */
void OWWriteByte(int8 data)
{
   int8 i;
   
   for (i = 0; i < 8; i++)
   {
      output_low(OW_PIN);
      delay_us(2);      
      output_bit(OW_PIN, shift_right(&data, 1, 0));
      delay_us(60);
      output_float(OW_PIN);
      delay_us(2);
   }   
}

/*   OWReadByte()
 *   Description:
 *      Read a byte of data from the 1-Wire slaves
 *   Returns:
 *      A byte of data
 */
int8 OWReadByte(void)
{
   int8 i, data;
   
   for (i = 0; i < 8; i++)
   {
      output_low(OW_PIN);
      delay_us(2);
      output_float(OW_PIN);
      delay_us(8);
      shift_right(&data, 1, input(OW_PIN));
      delay_us(120);
   }
   
   return data;
}

//calc_CRC - INTERNAL FUNCTION
//Purpose:    To calculate an 8-bit CRC based on a polynomial and the series
//            of data bytes
//Note:       Polynomial used x^8 + x^5 + x^4 + 1 = 10001100
//Inputs:     A pointer to an array of the data bytes and an int saying how many
//            bytes there are in the data array
//Outputs:    An int8 which is the calculated CRC
int8 calc_CRC(int8* data, int8 bytes)
{
   #define CRC_POLY      0x8C
   int8 shift_register = 0, i, datab, bits;

   for(i = 0; i < bytes; ++i)
   {
      datab = *(data + i);

      for(bits = 0; bits < 8; ++bits)
      {
         if(bit_test((shift_register ^ datab), 0))
         {
            shift_register = shift_register >> 1;
            shift_register ^= CRC_POLY;
         }
         else
         {
            shift_register = shift_register >> 1;
         }

         datab = datab >> 1;
      }
   }
   return shift_register;
} //calc_CRC

// One wire crc
int8 ow_crc(int8 x)
{
   dowcrc = calc_CRC(x,8);
   return dowcrc;
}

/*   OWNext()
 *   Description:
 *      Searches for the next device on the 1-Wire device
 *   Result:
 *      Retuns false if no more devices are found
 */
int8 OWNext(void)
{
   int8 m = 1;             // ROM Bit index
   int8 n = 0;             // ROM Byte index
   int8 k = 1;             // Bit mask
   int8 x = 0;
   int8 discrepMarker = 0;
   int8 g;                 // Output bit
   int8 nxt;               // Return value
   short flag;

   nxt = FALSE;            // Reset next flag to false
   dowcrc = 0;             // Reset the dowcrc
   flag = OWReset();

   if (flag||doneFlag)     // If no parts return false
   {
      lastDiscrep = 0;     // Reset the search
      return FALSE;
   }
   
   OWWriteByte(0xF0);       // Send SearchROM command
   do
   {
      x = 0;
      if (OWReadBit() == 1)
         x = 2;
      delay_us(120);
      if (OWReadBit() == 1)
         x |= 1;                    // And it's complement 
      if (x == 3)                   // There are no devices on the one wire bus
         break;
      else
      {
         if (x > 0)                 // All devices coupled have 0 or 1
            g = x >> 1;             // Bit write value for search

         // If this discrepancy is before the last discrepancy on a previous
         // Next then pick the same as last time.
         else
         {
            if (m < lastDiscrep)
               g = ((RomBytes[n] & k) > 0);
            // If equal to last pick 1
            else
               g = (m == lastDiscrep);  // If not then pick 0

               // If 0 was picked then record position with mask k
               if (g == 0) discrepMarker = m;
         }

         // Isolate bit in ROM[n] with mask k
         if (g == 1) RomBytes[n] |= k;
         else RomBytes[n] &= ~k;

         OWWriteBit(g);  // ROM search write

         m++;           // Increment bit counter m
         k = k << 1;    // and shift the bit mask k
         // If the mask is 0 then go to new ROM
         if (k == 0)
         {  // Byte n and reset mask
            ow_crc(RomBytes[n]);      // Accumulate the crc
            n++;
            k++;
         }
      }
   } while (n < 8);  // Loop through until through all ROM bytes 0-7

   if (m < (65||dowcrc))   // If search was unsuccessful then
      lastDiscrep = 0;     // reset the last Discrepancy to zero
   else  // Search was successful, so set lastDiscrep, lastOne, nxt
   {
      lastDiscrep = discrepMarker;
      doneFlag = (lastDiscrep == 0);
      nxt = TRUE; // Indicates search not yet complete, more parts remain
   }

   return nxt;
}   

/*   OWFirst()
 *   Description:
 *      Search for the first device on the 1-Wire bus
 *   Returns:
 *      The result of OWNext()
 */
int8 OWFirst(void)
{
   lastDiscrep = 0;
   doneFlag = FALSE;
   return OWNext();    // Call Next and return it's return value;
}

/*   OWFindDevices()
 *   Description:
 *      Searches for all the devices on the 1-Wire bus
 *   Returns:
 *      Nothing
 */
int8 OWFindDevices(void)
{
   int8 m, cont = 0;
   if(!OWReset())
   {
      if(OWFirst())    // Begins when at least one part found
      {
         numROMs = 0;
         do
         {
            numROMs++; 
            cont++;
            for (m=0;m<8;m++)
            {
               FoundROM[numROMs][m] = RomBytes[m];
            }
         } while (OWNext());   // Continues until no additional                             
      }
   }
   return cont;   
}      


#endif


main.h
Code:
#ifndef MAIN_H
#define MAIN_H

#include<24HJ128GP502.h>

#device ADC=16

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOBSS                    //No boot segment
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOWRT                    //Program memory not write protected
#FUSES PR                       //Primary Oscillator
#FUSES NOCKSFSM                 //Clock Switching is disabled, fail Safe clock monitor is disabled
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES WINDIS                   //Watch Dog Timer in non-Window mode
#FUSES WPRES128                 //Watch Dog Timer PreScalar 1:128
#FUSES WPOSTS16                 //Watch Dog Timer PostScalar 1:32768
#FUSES NOPUT                    //No Power Up Timer
#FUSES IOL1WAY                  //Allows only one reconfiguration of peripheral pins
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES NORSS                    //No secure segment RAM
#FUSES NOSSS                    //No secure segment
#FUSES NOWRTSS                  //Secure segment not write protected
#FUSES NORBS                    //No Boot RAM defined
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOCOE                    //Device will reset into operational mode
#FUSES NOJTAG                   //JTAG disabled
#FUSES ICSP1                    //ICD uses PGC1/PGD1 pins
#FUSES NOALTI2C                 //I2C mapped to alternate pins

#use delay(clock=20000000)

#pin_select U1TX=PIN_B7
#pin_select U1RX=PIN_B5
#use rs232(UART1, baud=9600,parity=N,bits=8)

#endif //MAIN_H



main.c
Code:
#include "main.h"
#include "one_wire.c"

void main()
{
   int8 devCount = 0;
   
   devCount = OWFindDevices();
   
   printf("\n\rNumber of devices found: %u\n\r", devCount);
   
}


I am using the version 4.104 of the CCS compiler.
Swys



Joined: 24 Feb 2010
Posts: 22

View user's profile Send private message

PostPosted: Tue Apr 06, 2010 7:03 am     Reply with quote

OK, I got it working. I rewrote the code in the Maxim Application Note 187. Now I am able to get the number of devices, but it seems that the ROM numbers of the sensors are incorrect. If I program the PIC and run the program, I get one set of ROM numbers for the two sensors I've connected for testing. When I power down the circuit and power it up again, I get a completely different set of numbers. When I reprogram the PIC, I get the ROM numbers that I got when I first programmed the PIC.

This must mean that my code is wrong somewhere...can someone please have a look at it? I can't seem to find the problem...There must be something wrong with my OWNext() function.

Oh, and another turn of events is that, as soon as I have 3 sensors connected, the function goes completely haywire.

main.c
Code:
#include "main.h"
#include "one_wire.c"

int8 devCount = 0;

void main()
{
   int8 i = 0;
   
   printf("\n\rDetecting 1-Wire devices...\n\r");
   if (OWReset())
      printf("No 1-Wire devices found\n\r");
   else
   {
      printf("1-Wire device(s) detected!\n\r");
      printf("Finding 1-Wire device(s)...\n\r");
      
      devCount = OWFindDevices();
      
      printf("Found %u devices", devCount);
   }
}


one_wire.c
Code:
#ifndef ONE_WIRE_C
#define ONE_WIRE_C

#define OW_PIN PIN_A4

// Global variables
int8 LastDeviceFlag;
int8 LastDiscrepancy;
int8 LastFamilyDiscrepancy;
int8 last_zero;
int8 ROM_NO[8];
int8 ROM_LIST[10][8];      //List of ROM codes
int8 crc8;

/*   OWWriteBit()
 *   Description:
 *      Writes a single bit on the 1-Wire bus
 *   Returns:
 *      Nothing
 */
void OWWriteBit(int8 bitval)
{
   if (bitval)
   {
      //Write '1' bit
      output_low(OW_PIN);
      delay_us(6);
      output_float(OW_PIN);
      delay_us(64);
   }
   else
   {
      //Write '0' bit
      output_low(OW_PIN);
      delay_us(60);
      output_float(OW_PIN);
      delay_us(10);
   }   
}

/*   OWReadBit()
 *   Description:
 *      Reads a single bit from the 1-Wire bus
 *   Returns:
 *      The result from the read
 */
int8 OWReadBit(void)
{
   int8 value;
   
   output_low(OW_PIN);
   delay_us(6);
   output_float(OW_PIN);
   delay_us(9);
   value = input(OW_PIN);
   delay_us(55);
   
   return value;
}      

/*   OWReset()
 *   Description:
 *      Reset the 1-Wire bus slave devices and ready them for a command
 *   Returns:
 *      0 = Device(s) present
 *      1 = No device present
 */
int1 OWReset(void)
{
   int1 value = 0;
   
   output_low(OW_PIN);
   delay_us(480);         //Pull wire LOW for minimum of 480us
   output_float(OW_PIN);   //Let the line recover to its HIGH state
   delay_us(80);         //Wait for the device to transmit its presence
   value = input(OW_PIN);   //Receive device present signal
   delay_us(400);         //Complete the reset time slot
   
   return value;
}

/*   OWWriteByte()
 *   Description:
 *      Write a byte of data to the 1-Wire slaves
 *   Returns:
 *      Nothing
 */
void OWWriteByte(int8 data)
{
   int8 i;
   
   for (i = 0; i < 8; i++)
   {
      output_low(OW_PIN);
      delay_us(2);      
      output_bit(OW_PIN, shift_right(&data, 1, 0));
      delay_us(60);
      output_float(OW_PIN);
      delay_us(2);
   }   
}

/*   OWReadByte()
 *   Description:
 *      Read a byte of data from the 1-Wire slaves
 *   Returns:
 *      A byte of data
 */
int8 OWReadByte(void)
{
   int8 i, data;
   
   for (i = 0; i < 8; i++)
   {
      output_low(OW_PIN);
      delay_us(2);
      output_float(OW_PIN);
      delay_us(8);
      shift_right(&data, 1, input(OW_PIN));
      delay_us(120);
   }
   
   return data;
}

//calc_CRC - INTERNAL FUNCTION
//Purpose:    To calculate an 8-bit CRC based on a polynomial and the series
//            of data bytes
//Note:       Polynomial used x^8 + x^5 + x^4 + 1 = 10001100
//Inputs:     A pointer to an array of the data bytes and an int saying how many
//            bytes there are in the data array
//Outputs:    An int8 which is the calculated CRC
int8 calc_CRC(int8* data, int8 bytes)
{
   #define CRC_POLY      0x8C
   int8 shift_register = 0, i, datab, bits;

   for(i = 0; i < bytes; ++i)
   {
      datab = *(data + i);

      for(bits = 0; bits < 8; ++bits)
      {
         if(bit_test((shift_register ^ datab), 0))
         {
            shift_register = shift_register >> 1;
            shift_register ^= CRC_POLY;
         }
         else
         {
            shift_register = shift_register >> 1;
         }

         datab = datab >> 1;
      }
   }
   return shift_register;
} //calc_CRC

// One wire crc
int8 ow_crc(int8 x)
{
   crc8 = calc_CRC(x,8);
   return crc8;
}

/*   OWNext()
 *   Description:
 *      Searches for the next device on the 1-Wire device
 *   Result:
 *      Retuns false if no more devices are found
 */
int8 OWNext(void)
{
   int8 id_bit;
   int8 cmp_id_bit;
   int8 id_bit_number;
   int8 search_direction;
   int8 rom_byte_number;
   int8 search_result;
   int8 rom_byte_mask;
   
   //Initialize variables
   id_bit_number = 1;
   last_zero = 0;
   rom_byte_number = 0;
   rom_byte_mask = 1;
   search_result = 0;
   crc8 = 0;
   
   if (!LastDeviceFlag)
   {
      if (OWReset())
      {
         //Reset the search
         LastDiscrepancy = 0;
         LastDeviceFlag = false;
         LastFamilyDiscrepancy = 0;
         return false;
      }
      
      OWWriteByte(0xF0);
      
      //Do the search
      do
      {
         id_bit = OWReadBit();
         //delay_us(120);
         cmp_id_bit = OWReadBit();
         
         //printf("id_bit = %u\n\rcmp_id_bit = %u", id_bit, cmp_id_bit);
         
         if ((id_bit == 1) && (cmp_id_bit == 1))
            break;
         else
         {
            //All devices coupled have 0 or 1
            if (id_bit != cmp_id_bit)
               search_direction = id_bit;
            else
            {
               if (id_bit_number < LastDiscrepancy)
                  search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0);
               else
                  search_direction = (id_bit_number == LastDiscrepancy);
               
               if (search_direction == 0)
               {
                  last_zero = id_bit_number;
                  
                  if (last_zero < 9)
                     LastFamilyDiscrepancy = last_zero;
               }
            }
            
            if (search_direction == 1)
               ROM_NO[rom_byte_number] |= rom_byte_mask;
            else
               ROM_NO[rom_byte_number] &= ~rom_byte_mask;
               
            OWWriteBit(search_direction);
            
            id_bit_number++;
            shift_left(rom_byte_mask, 1, 0);
            
            if (rom_byte_mask == 0)
            {
               ow_crc(ROM_NO[rom_byte_number]);
               rom_byte_number++;
               rom_byte_mask = 1;
            }
         }
      }while(rom_byte_number < 8);
      
      if (!((ID_bit_number < 65) || (crc8 != 0)))
      {
         LastDiscrepancy = last_zero;
         
         if (LastDiscrepancy == 0)
            LastDeviceFlag = true;
         
         search_result = true;
      }
   }
   
   if (!search_result || !ROM_NO[0])
   {
      LastDiscrepancy = 0;
      LastDeviceFlag = false;
      LastFamilyDiscrepancy = 0;
      search_result = false;
   }
   
   return search_result;
}   

/*   OWFirst()
 *   Description:
 *      Search for the first device on the 1-Wire bus
 *   Returns:
 *      The result of OWNext()
 */
int8 OWFirst(void)
{
   LastDiscrepancy = 0;
   LastDeviceFlag = false;
   LastFamilyDiscrepancy = 0;
   
   return OWNext();
}

/*   OWFindDevices()
 *   Description:
 *      Searches for all the devices on the 1-Wire bus
 *   Returns:
 *      Nothing
 */
int8 OWFindDevices(void)
{
   int8 i;
   int8 count = 0;
   int8 rom_count = 0;
   
   if (OWFirst())
   {
      rom_count = 0;
      
      do
      {
         rom_count++;
         count++;
         
         for (i = 0; i < 8; i++)
         {
            ROM_LIST[rom_count][i] = ROM_NO[i];
         }
         
         printf("Device %u found: ", rom_count);
         
         printf("%X %X %X %X %X %X %X %X\n\r",
         ROM_LIST[rom_count][7], ROM_LIST[rom_count][6],
         ROM_LIST[rom_count][5], ROM_LIST[rom_count][4],
         ROM_LIST[rom_count][3], ROM_LIST[rom_count][2],
         ROM_LIST[rom_count][1], ROM_LIST[rom_count][0]);
      } while (OWNext());   
   }
   
   return count;   
}      


#endif
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Tue Apr 06, 2010 11:24 am     Reply with quote

Code:
      rom_count = 0;
     
      do
      {
         rom_count++;           <--  move this ....
         count++;
         
         for (i = 0; i < 8; i++)
         {
            ROM_LIST[rom_count][i] = ROM_NO[i];
         }

                               <--    ... to here
Move the rom_count++ to after the for-loop. Now your first found ROM will be random data and if 8 ROM's are found you'll be writing out of the array boundaries, overwriting other variables.
Swys



Joined: 24 Feb 2010
Posts: 22

View user's profile Send private message

PostPosted: Wed Apr 07, 2010 4:40 am     Reply with quote

Thanks ckielstra. Unfortunately, that didn't work... Sad

Ok, so I've found the Book of iButtonĀ® Standards (App Note 937). In section C.3. they discuss the Search ROM routine. I've reprogrammed my functions...AND IT WORKS! With one exception...if I have more than two sensors on the bus, it goes into a loop where it finds only the first two devices (which incidentily have similar ROM numbers, with little difference). I think my OWNext() function does not split the search path at the right location.

Below are my new OWNext(), OWFirst() and OWFindDevices() functions. Can anyone please look at this and help me find the problem?

Thanks.

Code:
/*   OWNext()
 *   Description:
 *      Searches for the next device on the 1-Wire device
 *   Result:
 *      Retuns false if no more devices are found
 */
int8 OWNext(void)
{
   int8 result;
   int8 rom_index;      //Counts to 64 for all the bits in the ROM number
   int8 bit_index = 0;   //When it is 8, a byte is completed
   int8 discrepancy;
   int8 bit_a;
   int8 bit_b;         //The complement reading of the devices
   int8 rom_byte_index = 0;
   int8 bit_val;
   
   result = false;
   
   
   if (LastDeviceFlag == true)
   {
      LastDeviceFlag = false;
      return result;
   }
   
   if (OWReset())
   {
      LastDiscrepancy = 0;
      return result;
   }
   else
   {
      //Presence signal detected
      rom_index = 1;
      discrepancy = 0;
      
      //Send search command
      OWWriteByte(0xF0);
      
      do
      {
         bit_a = OWReadBit();
         bit_b = OWReadBit();
         
         if ((bit_a == 1) && (bit_b == 1))
         {
            //No device found
            LastDiscrepancy = 0;
            return result;
         }
         else
         if ((bit_a == 0) && (bit_b == 0))
         {
            //Discrepancy found
            if (rom_index == LastDiscrepancy)
            {
               //Set ROM BIT(rom_index) = 1
               bit_val = 1;
            }   
            else
            if (rom_index > LastDiscrepancy)
            {
               //Set ROM BIT(rom_index) = 0
               bit_val = 0;
               discrepancy = rom_index;
            }
            else
            if (bit_val == 0)
            {
               discrepancy = rom_index;
            }
            else
            {
               //WAT GEBEUR HIER MET bit_val???
               //MAAK HOM DALK 1???
            }      
         }
         else
         {
            //Set ROM BIT(rom_index) = bit_a
            bit_val = bit_a;
         }
         
         if (bit_val == 0)
         {
            bit_clear(ROM_DATA[rom_byte_index], bit_index);
         }
         else
         {
            bit_set(ROM_DATA[rom_byte_index], bit_index);
         }   
         
         //Send ROM BIT(rom_index) on 1-Wire bus
         OWWriteBit(bit_val);
         
         //Increment rom_index
         rom_index++;
         
         //Increment the current byte's bit_index
         bit_index++;
         
         if (bit_index == 8)
         {
            bit_index = 0;
            rom_byte_index++;
         }
      
      }while (rom_index < 64);
      
      LastDiscrepancy = discrepancy;
      
      if (LastDiscrepancy == 0)
      {
         LastDeviceFlag = true;
         result = true;
      }
      else
      {
         result = true;
      }
      
      return result;
   }
}   

/*   OWFirst()
 *   Description:
 *      Search for the first device on the 1-Wire bus
 *   Returns:
 *      The result of OWNext()
 */
int8 OWFirst(void)
{
   LastDiscrepancy = 0;
   LastDeviceFlag = false;
   
   return OWNext();
}

/*   OWFindDevices()
 *   Description:
 *      Searches for all the devices on the 1-Wire bus
 *   Returns:
 *      Nothing
 */
int8 OWFindDevices(void)
{
   int8 i;
   int8 count = 0;
   int8 rom_count = 0;
   
   if (OWFirst())
   {
      count = 0;
      
      do
      {
         count++;
         
         printf("Device %u: ", count);
         for (i = 7; i >= 0; i--)
         {
            printf("%X ", ROM_DATA[i]);
         }
         
         printf("\n\r");   
         
      } while (OWNext());   
   }   
   
   return count;   
}
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