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

Assembly to C. Code not working right :(

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



Joined: 14 Jan 2004
Posts: 88
Location: Aurora, Ontario, Canada

View user's profile Send private message Visit poster's website

Assembly to C. Code not working right :(
PostPosted: Thu Jan 19, 2006 3:25 pm     Reply with quote

Hi.
I am trying to make a pic16F639 talk to its internal Low Frequency front end via software SPI.
The 639 is identical to a 636 but has an MCP2030 chip in the same package, connected via RC1,2,3.

I have sample code from microchip for their demo board, which is in assembler. I am therefor trying to rewrite it in C. This is where I am running into trouble.
I hooked up a couple of unused IO's to an RS232 port in so I can monitor the what is happening internally, which tells me this

AFE[0] = 0xA0 -- SPI_READ[0] = 0x0000
AFE[1] = 0x00 -- SPI_READ[1] = 0x0000
AFE[2] = 0x00 -- SPI_READ[2] = 0x0000
AFE[3] = 0x00 -- SPI_READ[3] = 0x0000
AFE[4] = 0x00 -- SPI_READ[4] = 0x0000
AFE[5] = 0x10 -- SPI_READ[5] = 0x0000
AFE[6] = 0x4F -- SPI_READ[6] = 0x0000

the SPI_reads should return the AFE data, shifted left one bit. As you can see, it is not happening.. I think I have stared myself blind looking at this, so if anyone has any suggestions it would be most welcome Smile
I can upload the entire Assembly if needed, but it is rather long. These are the sections which I have failing :(

Code:


   #define   AFECS   PORTC,1   ; Chip select output
   #define   SCK   PORTC,2   ; SPI Clock Output
   #define   SDIO   PORTC,3   ; Serial Data Input/Output
   #define   LFDATA   PORTC,3   ; Low Frequency Data IN

pin defines.
Code:

Set_up_AFE_Registers
   bsf   STATUS,RP0
   movfw   TRISC
   andlw   b'11000000'      ; chuck, Setup SDIO,SCLK, and CS as outputs
   movwf   TRISC         ;
   bcf   STATUS,RP0

;      Register 0: 0000-0001 - 0 (parity)   
;----------------------------------------------------
   movlw   WriteCommand+GeneralOptions+((AFEConfig0>>8)&0x01)
   movwf   SPIBufH
   movlw   AFEConfig0&0xFF
   movwf   SPIBufL
   call   ShiftOutSPIBuffer
;      Verify Register 0
   movlw   ReadCommand+GeneralOptions
   movwf   SPIBufH
   movlw   0x00
   movwf   SPIBufL
   call   ShiftOutSPIBuffer
   call   ShiftInSPIBuffer
   movfw   SPIBufL
   xorlw   AFEConfig0&0xFF
   btfss   STATUS,Z
   retlw   0x01

;      Register 1: 0000-0000 - 1 (parity)
;-------------------------------------------

this repeats for each register, trying to save space here Smile

Code:
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Subroutine: ShiftOutSPIBuffer
;   
; Description: This routine is used to shift data out of the microcontroller
;               onto the SPI bus.
;
;Notes:
;1.   This routine assumes 16-bit data is in SSPBufH and SSPBufL already.
;3.   Control the ports as follows:
;      Clear SCK/ALERT
;      Clear chip select
;Loop
;      Set or clear LFDATA/SDIO pin.
;      Set SCK/ALERT
;      Clear SCK/ALERT
;      Goto Loop 16 times
;      Set chip select
;Count00
;
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ShiftOutSPIBuffer
   movlw      .16
   movwf      Count00
   bcf      SCK
   bcf      AFECS
ShiftOutLoop
   rlf      SPIBufL, f
   rlf      SPIBufH, f
   btfss      STATUS, C
   bcf      SDIO
   btfsc      STATUS, C
   bsf      SDIO
   bsf      SCK
   bcf      SCK
;   CLRWDT
   decfsz      Count00, f
   goto      ShiftOutLoop
   bsf      AFECS
   bcf      AFECS
   return

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Subroutine: ShiftInSPIBuffer
;   
; Description: This routine is used to shift data into the microcontroller
;               from the SPI bus.
;
;Notes:
;1.   This routine loads 16-bit data into the SSPBufH and SSPBufL registers.
;3.   Control the ports as follows:
;      Clear SCK/ALERT
;      Clear chip select
;Loop
;      Set SCK/ALERT
;      Shift in the LFDATA/SDIO pin value.
;      Clear SCK/ALERT
;      Goto Loop 16 times
;      Set chip select
;Count00
;
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ShiftInSPIBuffer
   movlw      .16
   movwf      Count00
   bsf      STATUS,RP0
   bsf      TRISC,3      ;Set SDIO as an input
   bcf      STATUS,RP0
   bcf      SCK
   bcf      AFECS
ShiftInLoop
   bsf      SCK
   btfss      SDIO
   bcf      STATUS, C
   btfsc      SDIO
   bsf      STATUS, C
   rlf      SPIBufL, f
   rlf      SPIBufH, f
   bcf      SCK
;   CLRWDT
   decfsz      Count00, f
   goto      ShiftInLoop
   bsf      AFECS
   bcf      SCK
   bsf      STATUS,RP0
   bcf      TRISC,3      ;Set SDIO as an output
   bcf      STATUS,RP0
   return
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~




So here is my C code. as my first attempt using fancier looking functions failed, I tried duplicating the assembly as much as possible, yet I am still failing :(


Code:

#use rs232(baud=9600,parity=N,xmit=PIN_C0,rcv=PIN_C4,bits=8)


#include "interupt.c" // file with the Interrupt Service Routines in it.

void main()
{
    setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
    setup_timer_1(T1_DISABLED);
    setup_comparator(NC_NC_NC_NC);
    output_high(LF_CS);
//   output_low(LF_ALERT);
//   output_float(LF_ALERT);//

if( Set_Up_AFE_Registers()==0) {
   output_low(PIN_A5);
}
//  port_a_pullups(true);
//  set_tris_a(0x01); // only pin 1 is input.used to wake up the processor from the low frequency front end.
//   enable_interrupts(INT_EXT);
//  enable_interrupts(GLOBAL);
   printf("\n\r");
while(TRUE) {
   sleep();
   }//END WHILE
}// END MAIN
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
int Set_Up_AFE_Registers(void) {
int errorlevel=0;
int16 SPIREAD,TXDATA;
int i,address;

for(i=0;i<7;i++) {

address = SPI_WRITE_COMMAND | i;      //WRITE AFE Registers
TXDATA = make16(address,AFE[i]);
TXDATA = TXDATA << 1;   
TXDATA = parity16(TXDATA);
shift_out_SPI(TXDATA);               //READ AFE Registers
address = SPI_READ_COMMAND | i;         // Generate the SPI Read command
TXDATA = make16(address,0x00);
TXDATA = TXDATA << 1;   
//TXDATA = parity16(TXDATA); .. seems the sample source code does not have parity on the read byte.
shift_out_SPI(TXDATA); // Send the read command
SPIREAD=shift_in_spi();// now clock the data back in

delay_ms(100);
   printf("\r\nAFE[%d]      = 0x%X  -- ",i,AFE[i]);

   printf("SPI_READ[%d] = 0x%LX",i,SPIREAD);

}
return errorlevel;
}


///////////////////////////////////////////////////////////////////////////////
void shift_out_SPI(int16 DATA) {
int i;
output_low(LF_ALERT);
output_low(LF_CS);
for(i=0;i<16;i++) {
if(bit_test(DATA,0)) {
      output_high(LF_DATA);
   }
   else {
      output_low(LF_DATA);
   }
output_high(LF_ALERT);
output_low(LF_ALERT);
 DATA = DATA >> 1;
}//end for
output_high(LF_CS);
//output_low(LF_CS);
output_float(LF_ALERT);
}//end function
///////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
int16 shift_in_spi(void){
int16 RETDATA;
int DATA[2];
int i;
//set_tris_c(SPI_READ_Direction);
//output_float(LF_DATA);
output_low(LF_ALERT);
output_low(LF_CS);

for(i=0;i<16;i++) {
      shift_left(DATA,2,input(LF_DATA));
      output_high(LF_ALERT);
      output_low(LF_ALERT);
   }
output_high(LF_CS);
output_low(LF_ALERT);
//set_tris_c(SPI_WRITE_Direction);
RETDATA=make16(DATA[1],DATA[0]);
return RETDATA;
} // end function
///////////////////////////////////////////////////////////////////////////////






//**************************************************************************//


int16 parity16(int16 DATA) {
// Add parity to the DATA to be send to the Low frequency front end.
// the parity is ODD, and only on the 8 data bits, which are located at'D' "CCCAAAADDDDDDDDP"
//the parity is added in the LSB position.
int i;
int count=0;
int16 ReturnData;
ReturnData= DATA;
   for(i=0;i<8;i++) {
      if(DATA& 0x0001) {
         count++;
      }
      DATA=DATA>>1;
   }   
if(count%2 == 0){
   ReturnData = (ReturnData | 0x0001); // the 0x0002 is because we check the lsb of the data, which is not in the right most position, as that is where the parity bit is.
}
return ReturnData;
}


here is my pinout.h file

Code:

//RA_TRIS   EQU   B'00111111'
//RC_TRIS   EQU   B'00001110'
//   ENDIF
//   IFDEF P16F639
//                    _________
//                Vdd | 1  20 | Vss
//                 S0 | 2  19 | S5/SlowFall
//                 S1 | 3  18 | S4/LFDint
//                 S2 | 4  17 | S3/SHIFT/RFEN
//               DATA | 5  16 | LED1n          16F639
//              LED2n | 6  15 | RC1/CSn
//    RC3/LFDATA/SDIO | 7  14 | RC2/SCLK/Alert
//               Vddt | 8  13 | Vsst
//                LCZ | 9  12 | LCCOM
//                LCY | 10 11 | LCX
//                    ---------
   #define   S0   PORTA,5      // S0 BUTTON INPUT
   #define   S1   PORTA,4      // S1 BUTTON INPUT
   #define   S2   PORTA,3      // S2 BUTTON INPUT
   #define   S3   PORTA,2      // S3 BUTTON INPUT
   #define S4   PORTA,1      // S4 BUTTON INPUT
   #define LFDint   PORTA,1
   #define S5   PORTA,0      // S5 BUTTON INPUT

   #define   RFEN   PORTA,2   // RF ENABLE OUTPUT
   #define   RFENtris   TRISA,2
   #define   SHIFT   PORTA,2   // SHIFT BUTTON INPUT

   #define   LED   PORTC,0   // LED output
   #define   AFECS   PORTC,1   // Chip select output
   #define   SCK   PORTC,2   // SPI Clock Output
   #define   SDIO   PORTC,3   // Serial Data Input/Output
   #define   LFDATA   PORTC,3   // Low Frequency Data IN
   #define ValidLED   PORTC,4   // LED output
   #define   RFOUT   PORTC,5   // RF DATA OUTPUT



#define LF_CS PIN_C1
#define LF_ALERT PIN_C2
#define LF_DATA PIN_C3
#define SPI_CLK_DELAY 1
//Command(3 bits) address(4 bits) parity(1 bit) Odd Parity


#define SPI_CLAMP_ON          0x00
#define SPI_CLAMP_OFF          0x10
#define SPI_ENTER_SLEEP       0x20
#define SPI_AGC_PRESERVE_ON      0x30
#define SPI_AGC_PRESERVE_OFF   0x40
#define SPI_SOFT_RESET         0x50
#define SPI_READ_COMMAND      0x60
#define SPI_WRITE_COMMAND       0x70 // first 3 bits should be 111, followed by 4 address bits

// SPI Addresses
#define Config_Byte_0          0x00
#define Config_Byte_1          0x01
#define Config_Byte_2          0x02
#define Config_Byte_3          0x03
#define Config_Byte_4          0x04
#define Config_Byte_5          0x05
#define Colum_Parity           0x06
#define AFE_Status             0x07

#define STX 0x02
#define EOT 0x03
//#define TRUE 0x01
#define SPI_READ_Direction      0x08
#define SPI_WRITE_Direction      0x00
//******************************************************************************************
// Analogue Front End Configuration Table
//******************************************************************************************
// SGAFE Default Register Values
//      Default Mode:Wake-up filter disabled. MODSIG= 0, Enable Ch-X only. 25% mod depth.
//   Register 0: 1010-0001 - 0 (parity)

//   #define   AFEConfig0   0b10100000   //filter=enabled --> 2ms+2ms
   #define   AFEConfig0   0b10100000   //filter=enabled --> 2ms+2ms

//   Register 1: 0000-0000 - 1 (parity)
   #define   AFEConfig1   0b00000000

//   Register 2: 0000-0000 - 1 (parity)
   #define   AFEConfig2   0b00000000

//   Register 3: 0000-0000 - 1 (parity)
   #define   AFEConfig3   0b00000000

//   Register 4: 0000-0000 - 1 (parity)
   #define   AFEConfig4   0b00000000

//   Register 5: 0001-0000 - 0 (parity)
   #define   AFEConfig5   0b00010000   // modulation depth, default = 75%

//   Register 6: 0100-1111 - 0 (Parity) //  column parity bits
   #define   AFEConfig6   0b01001111   // column parity at defalt mode (75%)

char AFE[7]={AFEConfig0,AFEConfig1,AFEConfig2,AFEConfig3,AFEConfig4,AFEConfig5,AFEConfig6};

#define AFECOLPARITY AFEConfig0 xor AFEConfig1 xor AFEConfig2 xor AFEConfig3 xor AFEConfig4 xor AFEConfig0

PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jan 19, 2006 9:00 pm     Reply with quote

I think you should just post one routine that's not working.
Post the assembly, and then the one C routine that doesn't work.
Explain how you know that it doesn't work. Show the
expected output and the actual output.
ckielstra



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

View user's profile Send private message

PostPosted: Fri Jan 20, 2006 2:23 am     Reply with quote

I agree with PCM Programmer. I had a look at the code but didn't spot any obvious errors. It is a lot of code and I don't know what to look for so I stopped checking after 1 minute. If you want quick and usefull responses than give us a small compilable program that shows your problem.
Kasper



Joined: 14 Jan 2004
Posts: 88
Location: Aurora, Ontario, Canada

View user's profile Send private message Visit poster's website

PostPosted: Fri Jan 20, 2006 12:08 pm     Reply with quote

PCM programmer wrote:
I think you should just post one routine that's not working.
Post the assembly, and then the one C routine that doesn't work.
Explain how you know that it doesn't work. Show the
expected output and the actual output.


I expected this:
Code:

AFE[0] = 0xA0 -- SPI_READ[0] = 0x0000
AFE[1] = 0x00 -- SPI_READ[1] = 0x0000
AFE[2] = 0x00 -- SPI_READ[2] = 0x0000
AFE[3] = 0x00 -- SPI_READ[3] = 0x0000
AFE[4] = 0x00 -- SPI_READ[4] = 0x0000
AFE[5] = 0x10 -- SPI_READ[5] = 0x0000
AFE[6] = 0x4F -- SPI_READ[6] = 0x0000

as in I program in 0xA0 and read back 0x0000 ( the LSB << 1 contains the data)
I know I posted alot of code Embarassed but I am not sure if it is the write or the read routine which is not working. I verify by using a spare pin as a software RS232 port, printing out debug information..

I will work on it a bit more and see if I can spot where it goes wrong.

Thanks again for looking at it Smile

Kasper
Kasper



Joined: 14 Jan 2004
Posts: 88
Location: Aurora, Ontario, Canada

View user's profile Send private message Visit poster's website

PostPosted: Fri Jan 20, 2006 12:16 pm     Reply with quote

Code:

ShiftOutSPIBuffer
   movlw      .16
   movwf      Count00
   bcf      SCK
   bcf      AFECS
ShiftOutLoop
   rlf      SPIBufL, f
   rlf      SPIBufH, f
   btfss      STATUS, C
   bcf      SDIO
   btfsc      STATUS, C
   bsf      SDIO
   bsf      SCK
   bcf      SCK
;   CLRWDT
   decfsz      Count00, f
   goto      ShiftOutLoop
   bsf      AFECS
   bcf      AFECS
   return


versus
Code:
void shift_out_SPI(int16 DATA) {
int i;
output_low(LF_ALERT);
output_low(LF_CS);
for(i=0;i<16;i++) {
if(bit_test(DATA,0)) {
      output_high(LF_DATA);
   }
   else {
      output_low(LF_DATA);
   }
output_high(LF_ALERT);
output_low(LF_ALERT);
 DATA = DATA >> 1;
}//end for
output_high(LF_CS);
//output_low(LF_CS);
output_float(LF_ALERT);
}//end function


Anything which stands out as being blatantly wrong?


Looking at the disassembly listing, wow is C ever creating alot more code than assembly
Code:
82:                void shift_out_SPI(int16 DATA) {
83:                int i;
84:                output_low(LF_ALERT);
   0D4    1683     BSF 0x3, 0x5
   0D5    1107     BCF 0x7, 0x2
   0D6    1283     BCF 0x3, 0x5
   0D7    1107     BCF 0x7, 0x2
85:                output_low(LF_CS);
   0D8    1683     BSF 0x3, 0x5
   0D9    1087     BCF 0x7, 0x1
   0DA    1283     BCF 0x3, 0x5
   0DB    1087     BCF 0x7, 0x1
86:                for(i=0;i<16;i++) {
   0DC    01BF     CLRF 0x3f
   0DD    083F     MOVF 0x3f, W
   0DE    3C0F     SUBLW 0xf
   0DF    1C03     BTFSS 0x3, 0
   0E0    28F9     GOTO 0xf9
87:                if(bit_test(DATA,0)) {
   0E1    1C3D     BTFSS 0x3d, 0
   0E2    28E8     GOTO 0xe8
88:                      output_high(LF_DATA);
   0E3    1683     BSF 0x3, 0x5
   0E4    1187     BCF 0x7, 0x3
   0E5    1283     BCF 0x3, 0x5
   0E6    1587     BSF 0x7, 0x3
89:                   }
90:                   else {
   0E7    28EC     GOTO 0xec
91:                      output_low(LF_DATA);
   0E8    1683     BSF 0x3, 0x5
   0E9    1187     BCF 0x7, 0x3
   0EA    1283     BCF 0x3, 0x5
   0EB    1187     BCF 0x7, 0x3
92:                   }
93:                output_high(LF_ALERT);
   0EC    1683     BSF 0x3, 0x5
   0ED    1107     BCF 0x7, 0x2
   0EE    1283     BCF 0x3, 0x5
   0EF    1507     BSF 0x7, 0x2
94:                output_low(LF_ALERT);
   0F0    1683     BSF 0x3, 0x5
   0F1    1107     BCF 0x7, 0x2
   0F2    1283     BCF 0x3, 0x5
   0F3    1107     BCF 0x7, 0x2
95:                 DATA = DATA >> 1;
   0F4    1003     BCF 0x3, 0
   0F5    0CBE     RRF 0x3e, F
   0F6    0CBD     RRF 0x3d, F
96:                }//end for
   0F7    0ABF     INCF 0x3f, F
   0F8    28DD     GOTO 0xdd
97:                output_high(LF_CS);
   0F9    1683     BSF 0x3, 0x5
   0FA    1087     BCF 0x7, 0x1
   0FB    1283     BCF 0x3, 0x5
   0FC    1487     BSF 0x7, 0x1
98:                //output_low(LF_CS);
99:                output_float(LF_ALERT);
   0FD    1683     BSF 0x3, 0x5
   0FE    1507     BSF 0x7, 0x2
100:               }//end function
   0FF    1283     BCF 0x3, 0x5
   100    3400     RETLW 0
Shocked
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jan 20, 2006 12:45 pm     Reply with quote

Yes. The ASM code is shifting the 16-bit value to the left.
It shifts the MSB into the CY flag, and then tests it.
So it's shifting out the word "MSB first".
Code:

rlf      SPIBufL, f
rlf      SPIBufH, f
btfss    STATUS, C


But your C code is shifting it out "LSB first". You're doing a right-shift
and you're testing the LSB. You're doing the opposite of what the ASM
code is doing.
Code:

DATA = DATA >> 1;

if(bit_test(DATA,0))
Kasper



Joined: 14 Jan 2004
Posts: 88
Location: Aurora, Ontario, Canada

View user's profile Send private message Visit poster's website

PostPosted: Fri Jan 20, 2006 1:07 pm     Reply with quote

PCM programmer wrote:
Yes. The ASM code is shifting the 16-bit value to the left.
It shifts the MSB into the CY flag, and then tests it.
So it's shifting out the word "MSB first".
Code:

rlf      SPIBufL, f
rlf      SPIBufH, f
btfss    STATUS, C


But your C code is shifting it out "LSB first". You're doing a right-shift
and you're testing the LSB. You're doing the opposite of what the ASM
code is doing.
Code:

DATA = DATA >> 1;

if(bit_test(DATA,0))


Quoting a famous Cartoon Caracter...

DOH!

thanks PCM.. I am sure that will make one hell of a difference Smile
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