|
|
View previous topic :: View next topic |
Author |
Message |
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
Dynamic Parity Changes |
Posted: Wed Nov 19, 2003 4:09 pm |
|
|
I'm writing code that will need to change parity requirements on the fly as required by the network connection. Because I'm planing to use an interupt driven transmit routine the parity calculation must be as fast as possiable. I also need to be able to use no parity. The #use rs232 does not support this sort of thing. I can manually setup 9 or 8 bit mode as required. The following code uses 9 unneeded goto statements, one for each bit test.
Code: |
.................... Byte_To_Send=25;
0022: MOVLW 19
0024: MOVWF 05
....................
.................... if(USE_Parity) // Only solve parity if it will be used
.................... { TX9D=0; // Set Even parity
0026: BTFSS 06.0
0028: GOTO 0076
002C: BCF FAC.0
.................... if(Parity_ODD) TX9D=1; // Test/Set Odd parity??
002E: BTFSS 06.1
0030: GOTO 0036
0034: BSF FAC.0
.................... if(Tx_Bit_0) TX9D=!TX9D;
0036: BTFSS 05.0
0038: GOTO 003E
003C: BTG FAC.0
.................... if(Tx_Bit_1) TX9D=!TX9D;
003E: BTFSS 05.1
0040: GOTO 0046
0044: BTG FAC.0
.................... if(Tx_Bit_2) TX9D=!TX9D;
0046: BTFSS 05.2
0048: GOTO 004E
004C: BTG FAC.0
.................... if(Tx_Bit_3) TX9D=!TX9D;
004E: BTFSS 05.3
0050: GOTO 0056
0054: BTG FAC.0
.................... if(Tx_Bit_4) TX9D=!TX9D;
0056: BTFSS 05.4
0058: GOTO 005E
005C: BTG FAC.0
.................... if(Tx_Bit_5) TX9D=!TX9D;
005E: BTFSS 05.5
0060: GOTO 0066
0064: BTG FAC.0
.................... if(Tx_Bit_6) TX9D=!TX9D;
0066: BTFSS 05.6
0068: GOTO 006E
006C: BTG FAC.0
.................... if(Tx_Bit_7) TX9D=!TX9D;
006E: BTFSS 05.7
0070: GOTO 0076
0074: BTG FAC.0
.................... }
.................... putc(Byte_To_Send);
0076: MOVF 05,W
0078: BTFSS F9E.4
007A: GOTO 0078
007E: MOVWF FAD
|
Is there some option to turn off ICD compatability or improve optimization? I would not be so bothered by this except for the fact it has to occure within an interupt. Do I need to just write the routine in assembly? |
|
|
Haplo
Joined: 06 Sep 2003 Posts: 659 Location: Sydney, Australia
|
|
Posted: Wed Nov 19, 2003 5:05 pm |
|
|
From the older posts I remember that you can have two (or more) #use RS232 statements with overlapping pins. So I guess one way would be having two #use RS232 lines, one with parity and one without, different stream names and both using the same receive and transmit pins. Then based on your parity requirements you can choose which stream to use.
I haven't done this myself but it should work. |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
|
Posted: Thu Nov 20, 2003 9:59 am |
|
|
I had thought that using more than one #use 232 would work but I cant just use an if statement to check if parity is needed and apply the correct #use statement. The putc() statement is different when using parity. I cant have an interupt transmitting and a function in main chaning the parity on the fly.
Here is an example using no parity.
Code: |
CCS PCH C Compiler, Version 3.180, 18844
Filename: R:\Controlinc Group\TEC2000\Source\Function Library\test parity.LST
ROM used: 54 (0%)
Largest free fragment is 0
RAM used: 7 (0%) at main() level
7 (0%) worst case
Stack: 0 locations
*
0000: GOTO 0004
.................... #include "18F6720.h"
.................... //////// Standard Header file for the PIC18F6720 device ////////////////
.................... #device PIC18F6720
.................... #list
....................
.................... #use delay(clock=4194304)
.................... int8 TXBYTE;
.................... #use rs232(baud=9600,xmit=pin_c6,rcv=pin_c7,PARITY=N,ERRORS,stream=chanA)
*
0014: CLRF 06
0016: MOVLW 1A
0018: MOVWF FAF
001A: MOVLW 26
001C: MOVWF FAC
001E: MOVLW 90
0020: MOVWF FAB
.................... void Main(void)
.................... {
*
0004: CLRF FF8
0006: BCF FD0.7
0008: CLRF FEA
000A: CLRF FE9
000C: MOVLW 0F
000E: MOVWF FC1
0010: MOVLW 07
0012: MOVWF FB4
.................... TXBYTE=6; // Estabilish what byte is going to be transmitted
*
0022: MOVLW 06
0024: MOVWF 05
.................... putc(TXBYTE); // Load the transmit buffer to start transmition
0026: MOVF 05,W
0028: BTFSS F9E.4
002A: GOTO 0028
002E: MOVWF FAD
.................... while(1);
0030: GOTO 0030
.................... }
....................
0034: SLEEP
|
Here is an example using odd parity.
Code: |
CCS PCH C Compiler, Version 3.180, 18844
Filename: R:\Controlinc Group\TEC2000\Source\Function Library\test parity.LST
ROM used: 98 (0%)
Largest free fragment is 0
RAM used: 7 (0%) at main() level
9 (0%) worst case
Stack: 1 locations
*
0000: GOTO 0032
.................... #include "18F6720.h"
.................... //////// Standard Header file for the PIC18F6720 device ////////////////
.................... #device PIC18F6720
.................... #list
....................
.................... #use delay(clock=4194304)
.................... int8 TXBYTE;
.................... #use rs232(baud=9600,xmit=pin_c6,rcv=pin_c7,PARITY=O,ERRORS,stream=chanA)
0004: MOVLW 08
0006: MOVWF 01
0008: CLRF 08
000A: INCF 08,F
000C: MOVF 07,W
000E: MOVWF 00
0010: MOVF 00,W
0012: XORWF 08,F
0014: RRCF 00,F
0016: DECFSZ 01,F
0018: GOTO 0010
001C: BTFSS F9E.4
001E: GOTO 001C
0022: MOVLW FE
0024: ANDWF FAC,F
0026: BTFSC 08.0
0028: BSF FAC.0
002A: MOVF 07,W
002C: MOVWF FAD
002E: GOTO 005C (RETURN)
*
0042: CLRF 06
0044: MOVLW 1A
0046: MOVWF FAF
0048: MOVLW 66
004A: MOVWF FAC
004C: MOVLW D0
004E: MOVWF FAB
.................... void Main(void)
.................... {
*
0032: CLRF FF8
0034: BCF FD0.7
0036: CLRF FEA
0038: CLRF FE9
003A: MOVLW 0F
003C: MOVWF FC1
003E: MOVLW 07
0040: MOVWF FB4
.................... TXBYTE=6; // Estabilish what byte is going to be transmitted
*
0050: MOVLW 06
0052: MOVWF 05
.................... putc(TXBYTE); // Load the transmit buffer to start transmition
0054: MOVFF 05,07
0058: GOTO 0004
.................... while(1);
005C: GOTO 005C
.................... }
....................
0060: SLEEP
|
Code: |
#include "18F6720.h"
#use delay(clock=4194304)
#define TXSTA1 0xFAC // TRANSMIT STATUS AND CONTROL REGISTER
#bit TX91 = TXSTA1.6 // Parity enabler bit
#bit TX9D1 = TXSTA1.0 // Parity data bit
#bit TRMT = TXSTA1.1 // Transmit shift status full
int8 TXBYTE;
int1 Comm1_Odd;
#use rs232(baud=9600,xmit=pin_c6,rcv=pin_c7,ERRORS,stream=chanA)
#inline // Inline code runs faster & compiles smaller if called only once
void Comm1_Parity(void) // Solves parity for USART 1
{
if(TX91) // Only solve parity if it will be used
{
#asm
bcf TX9D1 // Start by assuming even parity
btfss Comm1_Odd // Make a test for odd parity
bsf TX9D1 // Set odd parity
btfsc TXBYTE, 0
btg TX9D1
btfsc TXBYTE, 1
btg TX9D1
btfsc TXBYTE, 2
btg TX9D1
btfsc TXBYTE, 3
btg TX9D1
btfsc TXBYTE, 4
btg TX9D1
btfsc TXBYTE, 5
btg TX9D1
btfsc TXBYTE, 6
btg TX9D1
btfsc TXBYTE, 7
btg TX9D1
#endasm
}
}
void Main(void)
{
TX91=1; // Estabilish that parity will be used. Can be changed on the fly
Comm1_Odd=0; // Estabilish that if parity will be used it will be odd. Can be changed on the fly
TXBYTE=6; // Estabilish what byte is going to be transmitted
Comm1_Parity(); // Set parity bit if parity is enabled
putc(TXBYTE); // Load the transmit buffer to start transmition
while(1);
}
|
This uses three extra instruction when parity is not required but supports changing on the fly and runs with the best possiable speed. Of course I still got to test it all out. |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Thu Nov 20, 2003 12:01 pm |
|
|
Take a look at this is you want to shave a few instructions off your parity calculation.
http://www.mindhertz.com/Parity.php
Here is another routine
;8-bit parity
;This routine will leave the parity of X in X.0
;while blenderizing most of the rest of X
swapf X, W ;x = abcdefgh w = efghabcd
xorwf X, F ;x = abcdefgh w = efghabcd
; xor efghabcd
rrf X, W ;x = abcdefgh w = -abcdefg
; xor efghabcd xor -efghabc
xorwf X, F ;x = abcdefgh w = -abcdefg
; xor efghabcd xor -efghabc
; xor -abcdefg
; xor -efghabc
; at this point, the parity for half the bits
; (a, b, e, and f) is in bit 2 of X, and the
; parity for the other half (bits c, d, g, and h)
; is in bit 0 of X.
btfsc X, 2 ; if the parity of (a,b,e,f) is 0,
; then the parity of (a,b,c,d,e,f,g,h)
; is equal to the parity of (c,d,g,h)...
; which is already in bit 0, so skip ahead.
incf X, F ; otherwise, the parity of (a,b,e,f) is 1,
; so the parity of (a,b,c,d,e,f,g,h) is
; NOT equal to the parity of (c,d,g,h).
; invert bit 0.
; at this point, bit 0 contains the parity of
; (a,b,c,d,e,f,g,h). |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
|
Posted: Thu Nov 20, 2003 12:45 pm |
|
|
Thats a really good read. I'm supprised CCS are not using that method in their USART functions. I was able to shave off 7 instruction cycles.
Thanks Mark.
Code: |
/***********************************************************
* Solve for parity bit on USART 1 *
***********************************************************/
#inline
void Comm1_Parity(void) // Solves parity for USART 1
{ Static int8 x;
if(TX91) // Only solve parity if it will be used
{ x=TXBYTE;
#asm
bcf TX9D1 // Start by assuming even parity
btfss Comm1_Odd // Make a test for odd parity
bsf TX9D1 // Set odd parity
swapf x, W // http://www.mindhertz.com/Parity.php
xorwf x, F // http://www.mindhertz.com/Parity.php
rrf x, W // http://www.mindhertz.com/Parity.php
xorwf x, F // http://www.mindhertz.com/Parity.php
btfsc x, 2 // http://www.mindhertz.com/Parity.php
incf x, F // http://www.mindhertz.com/Parity.php
btfsc x, 0 // If bit 0 is
btg TX9D1 // Toggle
#endasm
}
}
|
Still untested though I'm waiting for new hardware. |
|
|
piripic
Joined: 15 Jan 2008 Posts: 25
|
|
Posted: Fri Feb 01, 2008 2:06 pm |
|
|
Someone tried this trick ? I do not think that working, but I am not sure....
Not missing the XOR between X.0 and X.2 ?
Thanks
Claudio
Edit: I just simulated this example ...and.. wow, it works perfectly well without the XOR between x.0 and x.2. Excellent code
Last edited by piripic on Sat Feb 02, 2008 1:12 am; edited 1 time in total |
|
|
gjs_rsdi
Joined: 06 Feb 2006 Posts: 468 Location: Bali
|
parity |
Posted: Fri Feb 01, 2008 10:07 pm |
|
|
takes 29 or 31 PC
joseph
Code: | int paritycounter=0;
int bytetosend=0;
short int TX9D=0;
bytetosend=0b00000000;
paritycounter=0;
if (bit_test(bytetosend,0))
{
paritycounter++;
}
if (bit_test(bytetosend,1))
{
paritycounter++;
}
if (bit_test(bytetosend,2))
{
paritycounter++;
}
if (bit_test(bytetosend,3))
{
paritycounter++;
}
if (bit_test(bytetosend,4))
{
paritycounter++;
}
if (bit_test(bytetosend,5))
{
paritycounter++;
}
if (bit_test(bytetosend,6))
{
paritycounter++;
}
if (bit_test(bytetosend,7))
{
paritycounter++;
}
if (bit_test(paritycounter,0))
{
TX9D=1;
}
else
{
TX9D=0;
}
restart_wdt(); |
|
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
|
Posted: Sun Feb 03, 2008 3:24 am |
|
|
piripic wrote: | Someone tried this trick ? I do not think that working, but I am not sure....
Not missing the XOR between X.0 and X.2 ?
Thanks
Claudio
Edit: I just simulated this example ...and.. wow, it works perfectly well without the XOR between x.0 and x.2. Excellent code |
x.0 and x.2 each have half of the parity at that point. Testing one to toggle the other finishes it. |
|
|
piripic
Joined: 15 Jan 2008 Posts: 25
|
|
Posted: Sun Feb 03, 2008 11:59 am |
|
|
It is true! It has taken me a while 'to understand :-)
thx
Claudio |
|
|
|
|
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
|