00001 /*========================================================================= 00002 | (c) 2005-2007 Total Phase, Inc. 00003 |-------------------------------------------------------------------------- 00004 | Project : Cheetah Sample Code 00005 | File : async.c 00006 |-------------------------------------------------------------------------- 00007 | Use the asynchronous interface of the Cheetah host adapter 00008 |-------------------------------------------------------------------------- 00009 | Redistribution and use of this file in source and binary forms, with 00010 | or without modification, are permitted. 00011 | 00012 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00013 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00014 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00015 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00016 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00017 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00018 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00019 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00020 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00021 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00022 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00023 | POSSIBILITY OF SUCH DAMAGE. 00024 ========================================================================*/ 00025 00026 //========================================================================= 00027 // INCLUDES 00028 //========================================================================= 00029 #include <math.h> 00030 #include <stdio.h> 00031 #include <stdlib.h> 00032 #include <string.h> 00033 #include "cheetah.h" 00034 #include <fftw3.h> 00035 00036 #ifdef _WIN32 00037 #include <time.h> 00038 #else 00039 #include <sys/time.h> 00040 #endif 00041 00042 00043 //========================================================================= 00044 // CONSTANTS 00045 //========================================================================= 00046 // Uncomment to show the data returned by the shifting device 00047 #define SHOW_DATA 00048 00049 // Add a delay between bytes by changing this constant (in nanoseconds) 00050 #define BYTE_DELAY 0 00051 00052 00053 #define MAX_TX_LENGTH 3072 00054 00055 const int N_FFT = 1024; 00056 00057 00058 00059 //========================================================================= 00060 // UTILITY FUNCTIONS 00061 //========================================================================= 00062 static s64 _timeMillis () { 00063 #ifdef _WIN32 00064 return ((s64)clock()) * 1000 / CLOCKS_PER_SEC; 00065 #else 00066 struct timeval tv; 00067 gettimeofday(&tv, 0); 00068 return ((s64)tv.tv_sec * 1000L) + (s64)(tv.tv_usec / 1000L); 00069 #endif 00070 } 00071 00072 00073 #ifndef max 00074 #define max( a, b ) ( ((a) > (b)) ? (a) : (b) ) 00075 #endif 00076 00077 #ifndef min 00078 #define min( a, b ) ( ((a) < (b)) ? (a) : (b) ) 00079 #endif 00080 00081 //========================================================================= 00082 // FUNCTIONS 00083 //========================================================================= 00084 static void _blast_async (Cheetah handle, u32 txnlen, u32 iter) { 00085 double elapsed, cycle_duration; 00086 u32 i,j,k; 00087 int count = 0; 00088 u08 data_out[2]; 00089 // u08 data_out[4]; 00090 // u08 *data_in; 00091 u08 data_in[MAX_TX_LENGTH]; 00092 int input; 00093 int ready_bit; 00094 int valid_data_point; 00095 s64 start, itteration_start; 00096 int ret; 00097 fftw_complex *data, *fft_result; 00098 //fftw_plan plan_forward; 00099 00100 00101 data = ( fftw_complex* ) fftw_malloc( sizeof( fftw_complex ) * N_FFT ); 00102 fft_result = ( fftw_complex* ) fftw_malloc( sizeof( fftw_complex ) * N_FFT ); 00103 00104 00105 // Opens file to write out data as column vector 00106 FILE *data1_output, *data2_output, *data3_output; 00107 data1_output = fopen("data.1.dat", "w"); 00108 data2_output = fopen("data.2.dat", "w"); 00109 data3_output = fopen("data.3.dat", "w"); 00110 if (data1_output == NULL || data2_output == NULL || data3_output == NULL) { 00111 fprintf(stderr, "Could not open files!!!"); 00112 exit(1); 00113 } 00114 00115 // Make a simple queue to just assert OE. 00116 ch_spi_queue_clear(handle); 00117 ch_spi_queue_oe(handle, 1); 00118 ch_spi_batch_shift(handle, 0, 0); 00119 00120 fprintf(stderr, "Beginning to queue SPI packets..."); 00121 // Queue the batch which is a sequence of SPI packets 00122 // (back-to-back) each of length 2. 00123 data_out[0] = 0xff; 00124 data_out[1] = 0xff; 00125 ch_spi_queue_clear(handle); 00126 // for (i = 0; i < N_FFT * txnlen; ++i) { 00127 for (i = 0; i < N_FFT * 3; ++i) { 00128 //ch_spi_queue_ss(handle, 0x1); 00129 00130 00131 //data_out[2] = (count >> 8) & 0xff; 00132 //data_out[3] = (count >> 0) & 0xff; 00133 00134 ++count; 00135 00136 //ch_spi_queue_array(handle, 2, data_out); 00137 //ch_spi_queue_ss(handle, 0x0); 00138 // Convert Slave 1 00139 ch_spi_queue_ss(handle, 0xF); 00140 ch_spi_queue_array(handle, 2, data_out); 00141 ch_spi_queue_ss(handle, 0xE); 00142 00143 // Convert Slave 2 00144 ch_spi_queue_ss(handle, 0xF); 00145 ch_spi_queue_array(handle, 2, data_out); 00146 ch_spi_queue_ss(handle, 0xD); 00147 00148 // Convert Slave 3 00149 ch_spi_queue_ss(handle, 0xF); 00150 ch_spi_queue_array(handle, 2, data_out); 00151 ch_spi_queue_ss(handle, 0xB); 00152 00153 } 00154 fprintf(stderr, " Done\n"); 00155 00156 fprintf(stderr, "Beginning asynchronous SPI packet transmission...\n"); 00157 start = _timeMillis(); 00158 itteration_start = _timeMillis(); 00159 00160 // First, submit first batch 00161 ch_spi_async_submit(handle); 00162 00163 for (i = 0; i < iter; ++i) { 00164 cycle_duration = ((double)(_timeMillis() - itteration_start)) / 1000; 00165 itteration_start = _timeMillis(); 00166 fprintf(stderr, "Packet %d...\n", i); 00167 // Submit another batch, while the previous one is in 00168 // progress. The application may even clear the current 00169 // batch queue and queue a different set of SPI 00170 // transactions before submitting this batch 00171 // asynchronously. 00172 ch_spi_async_submit(handle); 00173 00174 // The application can now perform some other functions 00175 // while the Cheetah is both finishing the previous batch 00176 // and shifting the current batch as well. In order to 00177 // keep the Cheetah's pipe full, this entire loop must 00178 // complete AND another batch must be submitted 00179 // before the current batch completes. 00180 ch_sleep_ms(1); 00181 00182 // Collect the previous batch 00183 //ret = ch_spi_async_collect(handle, txnlen, data_in); 00184 ret = ch_spi_async_collect(handle, N_FFT * 3, data_in); 00185 //elapsed = ((double)(_timeMillis() - start)) / 1000; 00186 00187 00188 //data_in = (u08 *)malloc(3); 00189 for (j = 0; j < N_FFT * 3; j += 6) { 00190 // for (j = 0; j < N_FFT; j +=2 ) { 00191 // SS2 Data 00192 input = (data_in[j] << 8) + data_in[j+1]; 00193 ready_bit = input & 0x4000; 00194 valid_data_point = (input & 0x3ffc) >> 2; 00195 // valid_data[j/2] = valid_data_point; 00196 fprintf(data2_output, "%d\n", valid_data_point); 00197 00198 // SS3 Data 00199 input = (data_in[j+2] << 8) + data_in[j+3]; 00200 ready_bit = input & 0x4000; 00201 valid_data_point = (input & 0x3ffc) >> 2; 00202 // valid_data[j/2 + 1] = valid_data_point; 00203 fprintf(data3_output, "%d\n", valid_data_point); 00204 // fprintf(data1_output, "%d ", valid_data_point); 00205 // data[j][0] = (double)valid_data_point; 00206 // data[j][1] = 0.0; 00207 00208 // SS1 Data 00209 input = (data_in[j+4] << 8) + data_in[j+5]; 00210 ready_bit = input & 0x4000; 00211 valid_data_point = (input & 0x3ffc) >> 2; 00212 // valid_data[j/2 + 2] = valid_data_point; 00213 fprintf(data1_output, "%d\n", valid_data_point); 00214 } 00215 00216 // Ensures communication is successful 00217 if (ret < 0) printf("status error: %s\n", ch_status_string(ret)); 00218 fflush(stdout); 00219 00220 //plan_forward = fftw_plan_dft_1d( N_FFT, data, fft_result, FFTW_FORWARD, FFTW_ESTIMATE ); 00221 //fftw_execute ( plan_forward ); 00222 00223 // Print FFT result 00224 //printf("Sampling frequency: %.6lf Hz\n", N_FFT / cycle_duration); 00225 //printf("Expected Index: %1.0f\n", 21000 * cycle_duration); 00226 00227 //fprintf(stderr, "Output FFT Result\n"); 00228 //for( k = max(21000 * cycle_duration - 20, 0) ; k < min(21000 * cycle_duration + 20, N_FFT); k++ ) { 00229 //fprintf(data1_output, "%2.2f ", sqrt(pow(fft_result[k][0],2) + pow(fft_result[k][1],2))); 00230 //fprintf(stderr, "|fft_result[%d]| = %2.2f\n", 00231 // k, sqrt(pow(fft_result[k][0],2) + pow(fft_result[k][1],2)) ); 00232 //} 00233 00234 //for( k = 0 ; k < N_FFT; k++ ) { 00235 // fprintf(data1_output, "%2.2f ", data[k][0]); 00236 //} 00237 k=0; 00238 //fprintf(data1_output, "\n"); 00239 //fprintf(stderr, "End of FFT Results\n"); 00240 00241 00242 // The current batch is now shifting out on the SPI 00243 // interface. The application can again do some more tasks 00244 // here but this entire loop must finish so that a new 00245 // batch is armed before the current batch completes. 00246 ch_sleep_ms(1); 00247 } 00248 elapsed = ((double)(_timeMillis() - start)) / 1000; 00249 fprintf(stderr, "Transmission complete. Data Collected.\n"); 00250 00251 fclose(data1_output); data1_output = NULL; 00252 fclose(data2_output); data2_output = NULL; 00253 fclose(data3_output); data3_output = NULL; 00254 00255 printf("Took %.2lf seconds to get the data.\n", elapsed); 00256 fflush(stdout); 00257 printf("Sampling frequency: %.6lf Hz\n", 3 * 3 * N_FFT * iter / elapsed); 00258 fflush(stdout); 00259 00260 // Collect batch the last batch 00261 //ret = ch_spi_async_collect(handle, 0, 0); 00262 //elapsed = ((double)(_timeMillis() - start)) / 1000; 00263 //printf("collected batch #%03d in %.5lf seconds\n", i+1, elapsed); 00264 //if (ret < 0) printf("status error: %s\n", ch_status_string(ret)); 00265 //fflush(stdout); 00266 } 00267 00268 00269 //========================================================================= 00270 // MAIN PROGRAM 00271 //========================================================================= 00272 int main (int argc, char *argv[]) { 00273 Cheetah handle; 00274 int port = 0; 00275 int bitrate = 0; 00276 u08 mode = 0; 00277 u32 txnlen; 00278 u32 iter; 00279 00280 if (argc < 5) { 00281 printf("usage: async PORT BITRATE TXN_LENGTH ITER\n"); 00282 printf("\n"); 00283 printf("TXN_LENGTH is the number of SPI packets, each of length\n"); 00284 printf("4 to queue in a single batch.\n"); 00285 printf("\n"); 00286 printf("ITER is the number of batches to process asynchronously.\n"); 00287 return 1; 00288 } 00289 00290 port = atoi(argv[1]); 00291 bitrate = atoi(argv[2]); 00292 txnlen = atoi(argv[3]); 00293 iter = atoi(argv[4]); 00294 00295 // Open the device 00296 handle = ch_open(port); 00297 if (handle <= 0) { 00298 printf("Unable to open Cheetah device on port %d\n", port); 00299 printf("Error code = %d (%s)\n", handle, ch_status_string(handle)); 00300 return 1; 00301 } 00302 printf("Opened Cheetah device on port %d\n", port); 00303 00304 printf("Host interface is %s\n", 00305 (ch_host_ifce_speed(handle)) ? "high speed" : "full speed"); 00306 00307 // Ensure that the SPI subsystem is configured. 00308 ch_spi_configure(handle, (mode >> 1), mode & 1, CH_SPI_BITORDER_MSB, 0x0); 00309 printf("SPI configuration set to mode %d, %s shift, SS[2:0] active low\n", 00310 mode, "MSB"); 00311 fflush(stdout); 00312 00313 // Power the target using the Cheetah adapter's power supply. 00314 ch_target_power(handle, CH_TARGET_POWER_ON); 00315 ch_sleep_ms(100); 00316 00317 // Set the bitrate. 00318 bitrate = ch_spi_bitrate(handle, bitrate); 00319 printf("Bitrate set to %d kHz\n", bitrate); 00320 fflush(stdout); 00321 00322 _blast_async(handle, txnlen, iter); 00323 00324 // Close and exit. 00325 ch_close(handle); 00326 return 0; 00327 }