www.micro-examples.com
Microcontroller circuits and source code examples
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
 

The PIC PAL library is ready
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    www.micro-examples.com Forum Index -> Discussion About the Examples
View previous topic :: View next topic  
Author Message
BrunoG
Site Admin


Joined: 22 Nov 2005
Posts: 636

PostPosted: Sun Jan 21, 2007 4:16 am    Post subject: The PIC PAL library is ready Reply with quote

Turn your PIC into a PAL video processor !

See here for details :
http://www.micro-examples.com/public/microex-navig/doc/089-pic-pal-tv

Comments are welcome Very Happy
_________________
BrunoG, Administrator
Back to top
View user's profile Send private message Send e-mail
Cyber



Joined: 25 Jan 2007
Posts: 1

PostPosted: Thu Jan 25, 2007 4:34 pm    Post subject: Some Questions Reply with quote

Hi Bruno,

First of all, your projects are outstanding - I like some of them very much (excuse me for my poor english) Confused

I am trying your PAL example on Easy Pic 4. I've used 18F4520 and reduced the lines from

Code:

#define PAL_Y      128


to

Code:

#define PAL_Y      64


in order to fit to my ROM/RAM space.

I've connected RE0 and GND to TV's input - but there are some unsync llines all over - no image shown.

So, here are my questions:

1. Is it OK to use EP4 or I need to Iron your sample circuit?
2. Do I need to modify more lines in your example code?

Thanks in advance, I am quite interested in this project.

Regards,

Angel
Back to top
View user's profile Send private message
BrunoG
Site Admin


Joined: 22 Nov 2005
Posts: 636

PostPosted: Thu Jan 25, 2007 7:36 pm    Post subject: Reply with quote

Hi Angel, thank you for your message Smile

1 -> Yes you can use EasyPIC4, just wire the two resistors R8 and R9 as shown on schematic :
http://www.micro-examples.com/public/microex-navig/doc/089-pic-pal-tv#17
try also different values of R9 from 470 to 100 ohms, or change R8 and R9 to a 1K potentiometer and adjust it until you get a stable video picture.

2 -> Yes, you should first reduce the height of the welcome picture like this :
Code:
        PAL_picture(0, 0, logo_bmp, 128, 64) ;         // paint picture

it is the user's responsibility with this function not to exceed boundaries, because the library does not check the sizes for better performance.

with this adjustments you should at least be able to display the top part of the welcome picture. the other library functions are supposed to check screen boundaries, and no adjustment should be necessary to get the second screen.

don't hesitate to ask for more help, and tell us if you can get any success Wink
_________________
BrunoG, Administrator
Back to top
View user's profile Send private message Send e-mail
Najman



Joined: 07 Apr 2007
Posts: 7
Location: Andorra

PostPosted: Sat Apr 07, 2007 7:09 pm    Post subject: PIC PAL Library Reply with quote

Hi there!

First of all, congartulation for all your work!

I am trying to make your PIC PAL project with a PICDEM2+, a 18F4525 with 20MHz crystal and the C18 compiler...

I ve made some changes in order to compile but i have some problems...

Could you tell me wich functions do I have to modify to work with a 20MHz crystal? Is it possible (any time problems?). I have changed the functions delay_us...

In the main function I try to output only a white screen(PAL_fill(0xFF) Wink but I get a black screen with some strange white dots passing through...

can u help me?

Thx.
_________________
"The difference between successful people and
unsuccessful people is that successful people
fail many more times than unsuccessful people.", Brian Tracy
Back to top
View user's profile Send private message Send e-mail MSN Messenger
BrunoG
Site Admin


Joined: 22 Nov 2005
Posts: 636

PostPosted: Sat Apr 07, 2007 10:30 pm    Post subject: Reply with quote

Hi Najman, thank you !

The PIC needs to be clocked at 40 Mhz (10 Mhz crystal + HS PLL) to run the PIC PAL library correctly.
A 20 Mhz clock would be possible with a lot of adjustments in the program, but the horizontal resolution would be divided by two...

Changing the crystal would be a lot easier !
_________________
BrunoG, Administrator
Back to top
View user's profile Send private message Send e-mail
Najman



Joined: 07 Apr 2007
Posts: 7
Location: Andorra

PostPosted: Sun Apr 08, 2007 2:44 pm    Post subject: Reply with quote

Ok man, I ll try it ant I ll tell u something!!!

cheers. Razz
_________________
"The difference between successful people and
unsuccessful people is that successful people
fail many more times than unsuccessful people.", Brian Tracy
Back to top
View user's profile Send private message Send e-mail MSN Messenger
Najman



Joined: 07 Apr 2007
Posts: 7
Location: Andorra

PostPosted: Wed Apr 11, 2007 10:14 am    Post subject: Reply with quote

Hi Bruno,

I have tried with a crystal of 10MHz with the HSPLL...

I ve modified some parts of the code concerning the time, hera are the modified lines:

In the PAL_Library:

#define PAL_HSYNC(d) PAL_BVID = 0 ; PAL_BSYNC = 0 ; Delay_us(d)
#define PAL_BLACK(d) PAL_BVID = 0 ; PAL_BSYNC = 1 ; Delay_us(d);

In the ISR:

if(PAL_lineCode & 2) Delay_us(PAL_DELAY4) ; else Delay_us(PAL_DELAY28 - 6) ;

if(PAL_lineCode & Cool Delay_us(PAL_DELAY4) ; else Delay_us(PAL_DELAY28) ;

if(PAL_lineCode & 32) Delay_us(PAL_DELAY4) ; else Delay_us(PAL_DELAY28) ;

And at the begining of the ISR, I put a value in TMR0L in order to have a 64us timer interrupt.


I am using a 18F4525 so as I don t have as much RAM as the 4620 I put only 45 lines:

#define PAL_Y 45

well with all this changes i see on the screen 16 white bars separated with a black line... It s a pitty I cannot upload a picture on the forum... It seems like I send 1 black bit every 7 white bits...
I m not used to work in assembler but in the definition of PAL_BLOCK_SHIFT you output on port D only 7 bits... Is that correct?

However when i look at the output signal on the scope, I see a good video signal except a small jitter(a small delay of 300ns every x frames or lines)

It would be great if I could send u some pictures in order to understand me better...

Hope u ll give me some advice!

thank you.

Smile
_________________
"The difference between successful people and
unsuccessful people is that successful people
fail many more times than unsuccessful people.", Brian Tracy
Back to top
View user's profile Send private message Send e-mail MSN Messenger
BrunoG
Site Admin


Joined: 22 Nov 2005
Posts: 636

PostPosted: Wed Apr 11, 2007 8:46 pm    Post subject: Reply with quote

Hello,

you can send me pictures by email, I will add them here.

PIC18F4525 and PIC18F4620 are the same, the only difference is the FLASH memory size : the program should work as it is, with the same number of video lines Exclamation
_________________
BrunoG, Administrator
Back to top
View user's profile Send private message Send e-mail
Najman



Joined: 07 Apr 2007
Posts: 7
Location: Andorra

PostPosted: Thu Apr 12, 2007 11:15 am    Post subject: Reply with quote

Hi bruno,

You are right about the Flas and the RAM, I said something without checking it... sorry Razz

But you didn't answer me this question:
"I m not used to work in assembler but in the definition of PAL_BLOCK_SHIFT you output on port D only 7 bits... Is that correct?
"

I ll send you the pictures as soon as I can.

Thx.
_________________
"The difference between successful people and
unsuccessful people is that successful people
fail many more times than unsuccessful people.", Brian Tracy
Back to top
View user's profile Send private message Send e-mail MSN Messenger
BrunoG
Site Admin


Joined: 22 Nov 2005
Posts: 636

PostPosted: Thu Apr 12, 2007 11:48 am    Post subject: Reply with quote

Hello,

not exactly :
there are 7 shifts (PAL_BLOCK_SHIFT) and one load (PAL_BLOCK_HEAD or PAL_BLOCK_LOAD) so that all 8 bits of PORTD are used Wink
_________________
BrunoG, Administrator
Back to top
View user's profile Send private message Send e-mail
BrunoG
Site Admin


Joined: 22 Nov 2005
Posts: 636

PostPosted: Thu Apr 12, 2007 9:22 pm    Post subject: Reply with quote

Najman wrote:
I ll send you the pictures as soon as I can.



thanks for the pictures, this is the most significant one.

did you make any changes to the PIC PAL library ?
the video line seems to be very short on your screen.
can you post the code of the main program ? it seems that screen memory is not correcty defined.
for example, to display vertical lines, it should be something like this (not tested) :

Code:
#include        "PAL_Library.h"

/*************
 * DEFINITIONS
 *************/
 
/*
 * number of vertical pixels
 * from 1 to 128 included
 * the more pixels you have :
 * - the less RAM you have
 * - the less MCU time you have
 */
#define PAL_Y      45

/********************
 * RAM VARIABLES
 ********************/
 
/*
 * screen memory map
 * do not change this line !
 */
unsigned char   PAL_screen[PAL_X * PAL_Y / 8] ;

/*
 * interrupt service routine
 */
void    interrupt(void)
        {
        /*
         * do PAL stuff
         */
        PAL_ISR() ;             // library call
        }

/*
 * main program
 */
void main(void)
        {
   /*
    * I/O configuration
    */
        ADCON1 = 0x0f ;
        TRISA = 0xff ;
        PORTA = 0 ;
       
        TRISB = 0xff ;
        PORTB = 0 ;
       
        TRISC = 0xff ;
        PORTC = 0 ;
       
        TRISD = 0 ;
        PORTD = 0 ;
       
        TRISE = 0 ;
        PORTE = 0 ;
       
   /*
    * start video and display first screen
    */
        PAL_init(PAL_Y) ;       // init PAL library
        PAL_fill(0xaa) ;           // feel screen with vertical lines
        PAL_control(PAL_CNTL_START, PAL_CNTL_RENDER) ;  // start video and rendering
        }

_________________
BrunoG, Administrator
Back to top
View user's profile Send private message Send e-mail
Najman



Joined: 07 Apr 2007
Posts: 7
Location: Andorra

PostPosted: Fri Apr 13, 2007 8:25 am    Post subject: Reply with quote

Hola Bruno,

What's up? thanks for having posted the picture... Cool

Yes I have modified the PAL_Library lightly in order to compile with the C18 Compiler... Exclamation

her is my code:

Code:


#define PAL_Y      45//128

unsigned char   PAL_screen[PAL_X * PAL_Y / 8] ;



/***************************************************************\
*                       Programa principal                  *
\***************************************************************/

void main (void)
{
      //************ Definicio Variables ***************
   unsigned char i ;
   unsigned int p;
      //************ Funcions inicials... ***************   
InitGeneral();

fprintf(_H_USER,"\r\nPrincipi programa");

//start video and display first screen
PAL_init(PAL_Y) ;       // init PAL library
PAL_fill(0xFF) ;           // clear screen

PAL_control(PAL_CNTL_START, PAL_CNTL_RENDER) ;  // start video and rendering

i = 0 ;

      //************ Programa principal ***************
while (1)
   {
   //   fprintf(_H_USER,"\r\nEstem en while");
   for (p=0;p<65000;p++)
      RB0=!RB0;
      
   }//while(1)
}//main




/***************************************************************\
*                       SubRutines                        *
\***************************************************************/

//**********************   InitGeneral
void InitGeneral(void)
{

//Init dels ports
TRISA = 0b11111111;
TRISB = 0b11111100;
TRISC = 0b11111111;
TRISD = 0b11111110;
TRISE = 0b00000110;

PORTA = 0;
PORTB = 0;     
PORTC = 0;
PORTD = 0;
PORTE = 0;
       
//Init entrades totes digitals   
ADCON0 = 0b00000000;
ADCON1 = 0b00001111;
ADCON2 = 0b00000000;

//Apaguem WDT
WDTCONbits.SWDTE=0;


//Configuracio Interrupcions

PIE1=0;
PIE2=0;

PEIE = 1;         
GIE  = 1;         
   
}//void InitGeneral(void)



/**************************************************************\
*                       SubRutines d INTERRUPCIO              *
\**************************************************************/
//obilguem al compilador a escriure les instruccions seguents al vector 0x08 (vector d'IT)
#pragma code high_vector = 0x08

void Interrupt_at_high_vector (void)
{
_asm goto ISR_NostraInt _endasm
}
#pragma code //Fi de obligacio de posar instruccions al vector 0x08

 
void ISR_NostraInt (void)
{
//estem en IT perque hem rebut un byte d'adreça(el nove bit es un 1)
//abans de comprovar cualsevol cosa mirem si hi ha agut errors en la com   

   PAL_ISR();
   
    GIE  = 1;   //no se perque es posa a ZERO!!!aixi que el torno a posar a 1 per seguretat
}//void ISR_NostraInt (void)




and here is the ISR, i Just put the timer to another value in orther to have a 64us interrupt, and I ve modified your Delay_us ...

Code:


void PAL_ISR(void)
{
        if(TMR0IF)
                {
                unsigned char a, b, c, d ;      // temporary registers
                TMR0H=0;   // A FER   
                TMR0L=86;//95;
              
                PAL_BVID = 0 ;                  // end of previous line
                PAL_BSYNC = 0 ;

                a = TBLPTRL ;                   // save PIC index registers (not done by compiler)
                b = TBLPTRH ;
                c = TBLPTRU ;
                d = TABLAT ;

                PAL_lineCode = *PAL_linePtr ;   // get curret line code

                if(PAL_lineCode == PAL_LVIDEO)  // is it a visible video line ?
                        {
                        unsigned char   *ptr ;  // temporary pointer
                        volatile char   dummy ; // dummy char to please compiler

                        /*
                         * start of video line
                         */

                        PAL_HSYNC(3) ;          // horizontal sync : low level
                        PAL_BSYNC = 1 ;         // ultra black

                        /*
                         * during ultra black level :
                         */
                        PAL_lineVideo++ ;               // next line number
                        if(PAL_lineVideo == 287)        // last line ?
                                {
                                // next step in line table
                                PAL_linePtr++ ;
                                PAL_lineIdx++ ;
                                }

                        /*
                         * points to the first 8 pixels of the line
                         */
                        ptr = PAL_screen + (((PAL_lineVideo - PAL_shift_y) & 0b11111110) << 3) ;

                        /*
                         * make left border
                         */
                        PAL_MAKE_BORDER ;

                        /*
                         * is rendering enabled and line number within limits ?
                         * if not, a border color line will be displayed
                         */
                        if(PAL_render && ((PAL_lineVideo >= PAL_shift_y) && (PAL_lineVideo < PAL_max_y)))
                                {
                                /*
                                 * yes, display one video line
                                 * one line is 16 bytes ( x 8 = 128 pixels)
                                 */
                                dummy = *ptr ;                        // dummy assignement lo let the compiler know PAL_ISR_ptr

                                PAL_BLOCK_HEAD ;                        // header

                                PAL_BLOCK_SHIFT ; PAL_BLOCK_LOAD ;      // shift bits, preload and load
                                PAL_BLOCK_SHIFT ; PAL_BLOCK_LOAD ;
                                PAL_BLOCK_SHIFT ; PAL_BLOCK_LOAD ;
                                PAL_BLOCK_SHIFT ; PAL_BLOCK_LOAD ;
                                PAL_BLOCK_SHIFT ; PAL_BLOCK_LOAD ;
                                PAL_BLOCK_SHIFT ; PAL_BLOCK_LOAD ;
                                PAL_BLOCK_SHIFT ; PAL_BLOCK_LOAD ;
                                PAL_BLOCK_SHIFT ; PAL_BLOCK_LOAD ;
                                PAL_BLOCK_SHIFT ; PAL_BLOCK_LOAD ;
                                PAL_BLOCK_SHIFT ; PAL_BLOCK_LOAD ;
                                PAL_BLOCK_SHIFT ; PAL_BLOCK_LOAD ;
                                PAL_BLOCK_SHIFT ; PAL_BLOCK_LOAD ;
                                PAL_BLOCK_SHIFT ; PAL_BLOCK_LOAD ;
                                PAL_BLOCK_SHIFT ; PAL_BLOCK_LOAD ;
                                PAL_BLOCK_SHIFT ; PAL_BLOCK_LOAD ;
                                PAL_BLOCK_SHIFT ;

                                PAL_MAKE_BORDER ;                       // make right border
                                }
                        }
                else
                        {
                        /*
                         * vertical synchronization
                         * decode the PAL_lineCode and build the 4 parts of the sync line
                         */
                        PAL_BSYNC = (PAL_lineCode & 1) ? 1 : 0 ;        // first part
                        if(PAL_lineCode & 2)
                           Delay10TCYx(4);
                        else
                           Delay10TCYx(22);//delay per 22us

                        PAL_linePtr++ ;
                        PAL_lineIdx++ ;
                        PAL_lineVideo = 0 ;
                        /*
                         * points to the next line type
                         */
                        if(PAL_lineIdx == sizeof(PAL_ltype))    // end of table ?
                                {
                                PAL_lineIdx = 0 ;               // back to start
                                PAL_linePtr = PAL_ltype;
                                //PAL_linePtr = &(PAL_ltype[0]);
                                PAL_frameCtr++ ;
                                }

                        PAL_BSYNC = (PAL_lineCode & 4) ? 1 : 0 ;        // second part
                        if(PAL_lineCode != PAL_LINFO)
                                {
                                  if(PAL_lineCode & 8)
               Delay10TCYx(4);
              else
               Delay10TCYx(28);
                        
                                PAL_BSYNC = (PAL_lineCode & 16) ? 1 : 0 ;       // third part
                                   if(PAL_lineCode & 32)
                    Delay10TCYx(4);
               else
               Delay10TCYx(28);
                                                   
                                PAL_BSYNC = (PAL_lineCode & 64) ? 1 : 0 ;       // fourth part (no delay is needed)
                                }

                        }

                TBLPTRL = a ;   // restore PIC index registers
                TBLPTRH = b ;
                TBLPTRU = c ;
                TABLAT = d ;

                TMR0IF = 0 ;     //      clear TIMER 0 interrupt flag
                }
}//void PAL_ISR()



well this is my code, hope you ll see something wrong...

see ya! Very Happy
_________________
"The difference between successful people and
unsuccessful people is that successful people
fail many more times than unsuccessful people.", Brian Tracy
Back to top
View user's profile Send private message Send e-mail MSN Messenger
BrunoG
Site Admin


Joined: 22 Nov 2005
Posts: 636

PostPosted: Fri Apr 13, 2007 9:38 am    Post subject: Reply with quote

Ok, you will have to change this macro definitions :
PAL_BLOCK_HEAD
PAL_BLOCK_SHIFT
PAL_BLOCK_LOAD
they are optimized for mikroC compiler, and they surely not fit C18 compiler array management, because they directly access a pointer managed by the mikroC compiler.

PAL_BLOCK_HEAD loads indirect access register FSR0 with address of the byte of the first pixel of the line to be displayed, and moves the byte to the PORTD register

PAL_BLOCK_SHIFT shifts PORTD and moves video memory map pointer at the same time

PAL_BLOCK_LOAD moves next byte to the be shifted to the PORTD register

you will also have to adjust every delay, even if it is a nop, accordingly to the code generated by the C18 compiler

it is quite a big work, because the library is higly time-sensitive, and higly dependent to the code produced by the compiler.

by the way, the library has been developed on an EasyPIC4 board, with no extra hardware but the two resistors and the silicon diode Wink
_________________
BrunoG, Administrator
Back to top
View user's profile Send private message Send e-mail
Najman



Joined: 07 Apr 2007
Posts: 7
Location: Andorra

PostPosted: Fri Apr 13, 2007 10:15 am    Post subject: Reply with quote

Hi,


I don't really understand when you say:
Quote:
"they are optimized for mikroC compiler"

in wich way is it optimised??? It's the same assembler language... isn't it?
I guess I can make the assembler code, but I don't understand what is going to change from yours...

Well, honestly I haven't analysed it, but here are my compiler's macros translation in assemble...

The Macros:
Code:

#define PAL_MAKE_BORDER _asm MOVFF PAL_border, PORTD _endasm

#define PAL_BLOCK_HEAD\
                        _asm MOVFF   ptr, FSR0L _endasm \
                        _asm MOVFF   ptr+1, FSR0H _endasm\
                        _asm MOVFF   POSTINC0, PORTD _endasm

#define PAL_BLOCK_SHIFT\
                        _asm INFSNZ   ptr, 1, 1  _endasm\
                        _asm INCF   ptr+1, 1, 1  _endasm\
                        _asm RRCF   PORTD, 1, 0  _endasm\
                        _asm MOVFF   ptr, FSR0L  _endasm\
                        _asm RRCF   PORTD, 1, 0  _endasm\
                        _asm MOVFF   ptr+1, FSR0H  _endasm\
                        _asm RRCF   PORTD, 1, 0  _endasm\
                        _asm nop  _endasm\
                        _asm RRCF   PORTD, 1, 0  _endasm\
                        _asm nop  _endasm\
                        _asm RRCF   PORTD, 1, 0  _endasm\
                        _asm nop  _endasm\
                        _asm RRCF   PORTD, 1, 0  _endasm\
                        _asm nop  _endasm\
                        _asm RRCF   PORTD, 1, 0  _endasm\
                  _asm nop  _endasm

#define PAL_BLOCK_LOAD\
                        _asm  MOVFF   POSTINC0, PORTD  _endasm





The assembler code
Code:

554:                                       PAL_MAKE_BORDER ;
  1478    C0BB     MOVFF 0xbb, 0xf83
  147A    FF83     NOP

568:                                               PAL_BLOCK_HEAD ;                        // header
  14C0    C004     MOVFF 0x4, 0xfe9
  14C2    FFE9     NOP
  14C4    C005     MOVFF 0x5, 0xfea
  14C6    FFEA     NOP
  14C8    CFEE     MOVFF 0xfee, 0xf83
  14CA    FF83     NOP
569:               
570:                                               PAL_BLOCK_SHIFT ;
  14CC    4B04     INFSNZ 0x4, F, BANKED
  14CE    2B05     INCF 0x5, F, BANKED
  14D0    3283     RRCF 0xf83, F, ACCESS
  14D2    C004     MOVFF 0x4, 0xfe9
  14D4    FFE9     NOP
  14D6    3283     RRCF 0xf83, F, ACCESS
  14D8    C005     MOVFF 0x5, 0xfea
  14DA    FFEA     NOP
  14DC    3283     RRCF 0xf83, F, ACCESS
  14DE    0000     NOP
  14E0    3283     RRCF 0xf83, F, ACCESS
  14E2    0000     NOP
  14E4    3283     RRCF 0xf83, F, ACCESS
  14E6    0000     NOP
  14E8    3283     RRCF 0xf83, F, ACCESS
  14EA    0000     NOP
  14EC    3283     RRCF 0xf83, F, ACCESS
  14EE    0000     NOP
571:                                               PAL_BLOCK_LOAD ;      // shift bits, preload and load
  14F0    CFEE     MOVFF 0xfee, 0xf83
  14F2    FF83     NOP




The only strange thing I can see it's a lot of Nops instructions...

This weekend, I ll try to work on it!

Thx bruno.
Najim.
_________________
"The difference between successful people and
unsuccessful people is that successful people
fail many more times than unsuccessful people.", Brian Tracy
Back to top
View user's profile Send private message Send e-mail MSN Messenger
BrunoG
Site Admin


Joined: 22 Nov 2005
Posts: 636

PostPosted: Fri Apr 13, 2007 12:07 pm    Post subject: Reply with quote

Najman wrote:
Hi,


I don't really understand when you say:
Quote:
"they are optimized for mikroC compiler"

in wich way is it optimised??? It's the same assembler language... isn't it?
I guess I can make the assembler code, but I don't understand what is going to change from yours...


Yes it is the same assembler language but mikroC and C18 don't produce the same micro-code.
for example, then entry and exit code of the ISR may be different, as well as the way the compilers handle memory arrays and pointers.

the result is that the wrong video memory location is displayed in your case, and you have also bad timings because the picture part of the video line is too short.

Najman wrote:
Well, honestly I haven't analysed it, but here are my compiler's macros translation in assemble...


It should be analysed in detail, you have to check at first if FSR0 is pointing to the correct video memory location.
_________________
BrunoG, Administrator
Back to top
View user's profile Send private message Send e-mail
Display posts from previous:   
Post new topic   Reply to topic    www.micro-examples.com Forum Index -> Discussion About the Examples All times are GMT + 1 Hour
Goto page 1, 2, 3  Next
Page 1 of 3

 
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