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

FT245 speed problems -> assembler?!

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



Joined: 25 Jan 2010
Posts: 36

View user's profile Send private message

FT245 speed problems -> assembler?!
PostPosted: Tue Jun 01, 2010 2:05 pm     Reply with quote

hello all

I've some speed problems with the ft245 from ftdi because, i need to read all 128Byte of the RX-buffer faster than 800us.

in this moment, the datas are read with a c function:
Code:

#define TXE                PIN_D9                        // Transmitt-enabmle pin
#define WR                 PIN_D11                       // Write pin (high peak)
#define RX                 PIN_D8                        // Receive data Pin
#define RD                 PIN_D10                       // Read pin (during read low)
#define PWREN              PIN_F6                        // configurations-status
#define USART_DDR_out      set_tris_d(0x0000 | (1<<9) | (1<<8)),set_tris_f(0x0007 | (1 << 6))
#define USART_DDR_in       set_tris_d(0x00F8 | (1<<9) | (1<<8)),set_tris_f(0x003F | (1 << 6))

#define D0                 PIN_F3                        // Data-Pins
#define D1                 PIN_F4
#define D2                 PIN_F5
#define D3                 PIN_D3
#define D4                 PIN_D4
#define D5                 PIN_D5
#define D6                 PIN_D6
#define D7                 PIN_D7

#define rxBuf_max          50                            // buffer size
static volatile int8 index_rxBuf_R = 0;                  // Index of last write RX-Buffer
static volatile int8 index_rxBuf_W = 0;                  // Index of last read RX-Buffer
static volatile int8 rxBuf[rxBuf_max + 1];               // RX-Buffer

void usart_rx(void){                                     // read function (polling)
   int8 data = 0;                                        // data
   if(input_state(RX) == 0){                             // if new data in the FTDI buffer
      if(index_rxBuf_W == rxBuf_max){                    // ringbuffer
         index_rxBuf_W = 0;
      }
      else{
         index_rxBuf_W ++;
      }

// take datas and set it dynamic in the buffer
      output_low(RD);                                    // read data
      if(input_state(D0) == 1) data |= (1 << 0);
      if(input_state(D1) == 1) data |= (1 << 1);
      if(input_state(D2) == 1) data |= (1 << 2);
      if(input_state(D3) == 1) data |= (1 << 3);
      if(input_state(D4) == 1) data |= (1 << 4);
      if(input_state(D5) == 1) data |= (1 << 5);
      if(input_state(D6) == 1) data |= (1 << 6);
      if(input_state(D7) == 1) data |= (1 << 7);
      rxBuf[index_rxBuf_W] = data;                       // store data
      output_high(RD);                                   // read finished
   }
}


then I woud call the function like this:
Code:

int i = 0;
for(i = 0; i < 128; i ++){
      usart_rx();
}


what effect to the speed has it, when I try to write the function usart_rx() and her call in assembler?
I wrote "try" because I have no mutch expirience with assembler.
Hope you can help me.

best wishes
P51D
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Tue Jun 01, 2010 2:28 pm     Reply with quote

The key to higher speed is a reasonable assignment of data pins, allowing to read the data at least in nibbles.
ckielstra



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

View user's profile Send private message

PostPosted: Tue Jun 01, 2010 3:04 pm     Reply with quote

List your:
- processor
- clock frequency
- compiler version

With a PIC18 and standard_io at 20MHz your code takes 602us.
With fast_io it is reduced to 577us.

Why are you reading all bits separately? It seems like your hardware is lined out to make it possible to read all 8 bits with a single input command.

Replace
Code:
      if(input_state(D0) == 1) data |= (1 << 0);
      if(input_state(D1) == 1) data |= (1 << 1);
      if(input_state(D2) == 1) data |= (1 << 2);
      if(input_state(D3) == 1) data |= (1 << 3);
      if(input_state(D4) == 1) data |= (1 << 4);
      if(input_state(D5) == 1) data |= (1 << 5);
      if(input_state(D6) == 1) data |= (1 << 6);
      if(input_state(D7) == 1) data |= (1 << 7);
      rxBuf[index_rxBuf_W] = data;                       // store data
by
Code:
      rxBuf[index_rxBuf_W] = input_d();                       // store data
423us with standard_io.
372us using fast_io

Thanks again for the Stopwatch function in the MPLAB Simulator. Cool
P51D



Joined: 25 Jan 2010
Posts: 36

View user's profile Send private message

PostPosted: Wed Jun 02, 2010 2:44 am     Reply with quote

Processor: ds30F6012A
Clock: 16MHz with fuse HS2_PLL16
Compiler: 4.107 ?(I think, because I'm now not at the right pc) with the PCWHD IDE

I used the fast-io version

And I'm reading the bits separtly, becaus in this hardware-version they are lined, but I don't know how it is in the next version.
The next problem is, that this is a 16 bit port and the other pins of these port are used to controll the ft245. how could I read and write only the lower byte?

and the oder problem is:
Quote:

128Byte of the RX-buffer faster than 800us

did you realy read all 128 bytes in 500us?

thank a lot for the answers

best regards
P51D
ckielstra



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

View user's profile Send private message

PostPosted: Wed Jun 02, 2010 4:55 am     Reply with quote

Quote:
And I'm reading the bits separtly, becaus in this hardware-version they are lined, but I don't know how it is in the next version.
Tell your hardware engineer it is important to you to have them in the right sequence and starting at port pin 0. If you don't discuss this it will be a gamble what he's up to, though it is easy for him to arrange the lines as you want them.

Quote:
did you realy read all 128 bytes in 500us?
On a PIC18 at 20MHz, yes. I don't have the PCWHD compiler so can't test for the DS30 at 16MHz. You can test this yourself using the free MPLAB IDE. Select the simulator as debugging device and use the stopwatch screen for measurements.

Quote:
how could I read and write only the lower byte?
Reading is easy, just throw away the unused part:
Code:
data8 = input_d() & 0x00FF;   // for the lower 8 bits
data8 = (input_d() >> 8) & 0x00FF;   // for the higher 8 bits

or use the CCS function make8:
data8 = make8(input_d(), 0);   // for the lower 8 bits
data8 = make8(input_d(), 1);   // for the higher 8 bits


Writing 8 bits to a 16 bit port means you'll first have to read the port, modify the data and then write back the result:
Code:
int8 data8 = 123;
int16 data16 = input_d();
data16 &= 0xFF00;        // clear lower 8 bits
data16 = data16 | data8; // Add the new 8 bit data
output_d(data16);
SET



Joined: 15 Nov 2005
Posts: 161
Location: Glasgow, UK

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Wed Jun 02, 2010 8:21 am     Reply with quote

In summary, you are reading a byte where the bits are split across two ports?

I would do something like:

Read 1st Port
Mask and shift
Read 2nd Port
Mask and shift
'or' them together

If need be you could then use the byte as an index into a look up table. Not be hugely faster but should save a few instructions?
P51D



Joined: 25 Jan 2010
Posts: 36

View user's profile Send private message

PostPosted: Wed Jun 02, 2010 9:00 am     Reply with quote

SET wrote:
In summary, you are reading a byte where the bits are split across two ports?


No, but the port is a 16 bit port with controll-pin.

I've tested it with the new read-function:
~200us but there where no data availlable in the rx-buffer from the ftdi.

there is also an other problem:
I can't do this with a for-loop because I need a main-programm-loop speed about <= 10 us.
reading with more steps would be the best way, or are there other possibilitys?

best wishes
P51D
P51D



Joined: 25 Jan 2010
Posts: 36

View user's profile Send private message

PostPosted: Thu Jun 03, 2010 6:21 am     Reply with quote

hello all

I've tested the new version with 126 bytes to rx.
Code:

void usart_rx(void){                                     // read function (polling)
   if(input_state(RX) == 0){                             // if new data in the FTDI buffer
      if(index_rxBuf_W == rxBuf_max){                    // ringbuffer
         index_rxBuf_W = 0;
      }
      else{
         index_rxBuf_W ++;
      }

// take datas and set it dynamic in the buffer
      output_low(RD);                                    // read data
      rxBuf[index_rxBuf_W] = ((input_d() & 0xF8) | ((input_f() & 0x38) >> 3)); // store data
      output_high(RD);                                   // read finished
   }
}

There are 2 ports for the FT245 because the others are used also to fast communications.

the receiving case of the Parameters looks like this:
Code:

switch(PAR_state){                                 // Werte in Ausgabe-Arrays speichern
   case waitRED:
      red_buf[k] = rxBuf[index_rxBuf_R];
      PAR_state = waitGREEN;
      break;
     
   case waitGREEN:
      green_buf[k] = rxBuf[index_rxBuf_R];
      PAR_state = waitBLUE;
      break;
     
   case waitBLUE:
      blue_buf[k] = rxBuf[index_rxBuf_R];
      PAR_state = waitAX1;
      break;
     
   case waitAX1:
      x_achse_buf[k] = (rxBuf[index_rxBuf_R] << 4);
      PAR_state = waitAX2;
      break;
     
   case waitAX2:
      x_achse_buf[k] |= (rxBuf[index_rxBuf_R] >> 4);               
      y_achse_buf[k] = ((rxBuf[index_rxBuf_R] & 0x0F) << 8);
      PAR_state = waitAX3;
      break;
     
   case waitAX3:   
      y_achse_buf[k] |= rxBuf[index_rxBuf_R];
      if(k == (Stream_buf_max - 1))                // Ringbuffer Steuerung
         k = 0;
      else
         k ++;
      PAR_state = waitRED;             
      if(index_par == NUM){
         RS232_state = waitACK;
         txBuf_Write(ACK);
         index_par = 0;
output_low(led_red);
      }


The LED is high for ~660us but after 700 us the datas were used. Is there a possibility to redefine the code for faster reading?

the hole sending and receiving protokoll looks like this:
Code:

void RS232(void){
   static unsigned int8 RS232_state = 0;                    // Protokollstatus
   static unsigned int16 index_par = 0;                     // Array-Variable für Parameters
   static unsigned int16 NUM = 0;                           // Anzahl zu übertragenden Werte
   static unsigned int1 num_teil = 0;                       // 16Bit Anzahl zusammensetzen
   static unsigned int16 k = 0;                             // Speichervariable für Steuerung
   static unsigned int8 PAR_state = 0;
   static unsigned int8 temp_cmd = 0;
   
   usart_tx();                                              // Wenn Daten im TX-Buffer, senden
   usart_rx();                                              // Wenn Daten im FTDI-Buffer, entgegennehmen

   if(index_rxBuf_W == index_rxBuf_R){                      // Buffer Error abgleichen
      return;                                               // Wenn keine neuen Daten => aus Funktion heraus springen
   }
   if(index_rxBuf_R == rxBuf_max){                          // Erhöhen
      index_rxBuf_R = 0;
   }
   else{
      index_rxBuf_R ++;
   }

   switch (RS232_state){         
      case waitENQ:
         switch (rxBuf[index_rxBuf_R]){
            case '?':                                       // Suche der LCU
               printf(txBuf_Write,"USB LCU");
               output_high(LED_green);
               break;
               
            case ENQ:
               RS232_state = waitSOH;                       // In nächsten State wechselnd
               txBuf_Write(ACK);
               break;
               
            default:
               txBuf_Write(rxBuf[index_rxBuf_R]);           // Unbekanter Befehl zurückgeben
               break;
         }
         break;
         
      case waitSOH:                                         // Header der Übertragung
         if (rxBuf[index_rxBuf_R] == SOH){
            RS232_state = waitCMD;
         }
         else{
            RS232_state = waitENQ;
            txBuf_Write(NACK);
         }
         break;
         
      case waitCMD:                                         // Kommando
         switch (rxBuf[index_rxBuf_R]){
            case STREAM:                                    // Werte streamen
               RS232_state = waitNUM;
               temp_cmd = rxBuf[index_rxBuf_R];
               break;
               
            case STOP:                                      // Projektor aus
               command = rxBuf[index_rxBuf_R];
               txBuf_Write(ACK);
               RS232_state = waitACK;
               break;
               
            case 0x01:                                      // Show 1
               command = rxBuf[index_rxBuf_R];
               txBuf_write(ACK);
               RS232_state = waitACK;
               break;
               
            default:
               RS232_state = waitENQ;
               txBuf_Write(NACK);
               command = 0;
               break;
         }
         break;
         
      case waitNUM:                                         // Anzahl zu empfangender Werte in 16 Bit
         if(num_teil == 0){                                 // 2 8Bit Werte zu 16 Bit Wert zusammensetzen
            NUM = (rxBuf[index_rxBuf_R] << 8);
            num_teil = 1;
         }
         else{
            NUM |= rxBuf[index_rxBuf_R];
            RS232_state = waitPAR;
            num_teil = 0;
         }
         break;
         
      case waitPAR:
         index_par ++;
output_high(LED_red);
         switch(PAR_state){                                 // Werte in Ausgabe-Arrays speichern
            case waitRED:
               red_buf[k] = rxBuf[index_rxBuf_R];
               PAR_state = waitGREEN;
               break;
               
            case waitGREEN:
              green_buf[k] = rxBuf[index_rxBuf_R];
               PAR_state = waitBLUE;
               break;
               
            case waitBLUE:
               blue_buf[k] = rxBuf[index_rxBuf_R];
               PAR_state = waitAX1;
               break;
               
            case waitAX1:
               x_achse_buf[k] = (rxBuf[index_rxBuf_R] << 4);
               PAR_state = waitAX2;
               break;
               
            case waitAX2:
               x_achse_buf[k] |= (rxBuf[index_rxBuf_R] >> 4);               
               y_achse_buf[k] = ((rxBuf[index_rxBuf_R] & 0x0F) << 8);
               PAR_state = waitAX3;
               break;
               
            case waitAX3:   
               y_achse_buf[k] |= rxBuf[index_rxBuf_R];
               if(k == (Stream_buf_max - 1))                // Ringbuffer Steuerung
                  k = 0;
               else
                  k ++;
               PAR_state = waitRED;             
               if(index_par == NUM){
                  RS232_state = waitACK;
                  txBuf_Write(ACK);
                  index_par = 0;
output_low(led_red);
               }
               break;
         }
         break; 
         
      case waitACK:
         if(rxBuf[index_rxBuf_R] == ACK){                   // ACK empfangen,
            RS232_state = waitEOT;
         }
         break;
         
      case waitEOT:                                         // Übertragung beendet
         if(rxBuf[index_rxBuf_R] == EOT){
            RS232_state = waitENQ;
            if(temp_cmd == STREAM){
               command = temp_cmd;
               temp_cmd = 0;
            }
         }
         break;
   }
}

Thank for helping

best wishes
P51D
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