ADAT (Alesis Digital Audio Tape) interface codec using STM32F411RE Nucleo board. ADAT frame encoding / decoding rate is ~113000 frames/s, faster than real-time needs (48000 frames/s) Future work will attempt to implement an 8-in / 8-out digital mixer using DMA SPI Rx+Tx with a behringer ada8200.

Dependencies:   mbed mbprt

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 // MCU ADAT frames encoding (proof of concept)
00002 // 8 24-bit audio data -> 8 32-bit NRZI encoded ADAT frames
00003 // 480000 ADAT frames are encoded within ~3s, so encoding should require 30% CPU time (STM32F411RE)
00004 // This might leave margin for:
00005 //   ADAT decoding (NRZI decoding is less CPU intensive)
00006 //   Audio mixing 8 in -> 8 out
00007 //   Rx SPI w/ DMA
00008 //   Tx SPI w/ DMA
00009 //
00010 // Encoding is fully unrolled (faster?), starting from last frame bits so that the compiler can make use of ROR instruction (does it?)
00011 // NOT TESTED with ADAT device
00012 // Result is displayed on terminal
00013 
00014 #include "mbed.h"
00015 #include "mbprt.h"
00016 #include <sstream>
00017  
00018 Timer t;
00019 
00020 // NRZI encoding LUT
00021 char lut[256] = {0x0, 0xff, 0xfe, 0x1, 0xfc, 0x3, 0x2, 0xfd, 0xf8, 0x7, 0x6, 0xf9, 0x4, 0xfb, 0xfa, 0x5,
00022 0xf0, 0xf, 0xe, 0xf1, 0xc, 0xf3, 0xf2, 0xd, 0x8, 0xf7, 0xf6, 0x9, 0xf4, 0xb, 0xa, 0xf5,
00023 0xe0, 0x1f, 0x1e, 0xe1, 0x1c, 0xe3, 0xe2, 0x1d, 0x18, 0xe7, 0xe6, 0x19, 0xe4, 0x1b, 0x1a, 0xe5,
00024 0x10, 0xef, 0xee, 0x11, 0xec, 0x13, 0x12, 0xed, 0xe8, 0x17, 0x16, 0xe9, 0x14, 0xeb, 0xea, 0x15,
00025 0xc0, 0x3f, 0x3e, 0xc1, 0x3c, 0xc3, 0xc2, 0x3d, 0x38, 0xc7, 0xc6, 0x39, 0xc4, 0x3b, 0x3a, 0xc5,
00026 0x30, 0xcf, 0xce, 0x31, 0xcc, 0x33, 0x32, 0xcd, 0xc8, 0x37, 0x36, 0xc9, 0x34, 0xcb, 0xca, 0x35,
00027 0x20, 0xdf, 0xde, 0x21, 0xdc, 0x23, 0x22, 0xdd, 0xd8, 0x27, 0x26, 0xd9, 0x24, 0xdb, 0xda, 0x25,
00028 0xd0, 0x2f, 0x2e, 0xd1, 0x2c, 0xd3, 0xd2, 0x2d, 0x28, 0xd7, 0xd6, 0x29, 0xd4, 0x2b, 0x2a, 0xd5,
00029 0x80, 0x7f, 0x7e, 0x81, 0x7c, 0x83, 0x82, 0x7d, 0x78, 0x87, 0x86, 0x79, 0x84, 0x7b, 0x7a, 0x85,
00030 0x70, 0x8f, 0x8e, 0x71, 0x8c, 0x73, 0x72, 0x8d, 0x88, 0x77, 0x76, 0x89, 0x74, 0x8b, 0x8a, 0x75,
00031 0x60, 0x9f, 0x9e, 0x61, 0x9c, 0x63, 0x62, 0x9d, 0x98, 0x67, 0x66, 0x99, 0x64, 0x9b, 0x9a, 0x65,
00032 0x90, 0x6f, 0x6e, 0x91, 0x6c, 0x93, 0x92, 0x6d, 0x68, 0x97, 0x96, 0x69, 0x94, 0x6b, 0x6a, 0x95,
00033 0x40, 0xbf, 0xbe, 0x41, 0xbc, 0x43, 0x42, 0xbd, 0xb8, 0x47, 0x46, 0xb9, 0x44, 0xbb, 0xba, 0x45,
00034 0xb0, 0x4f, 0x4e, 0xb1, 0x4c, 0xb3, 0xb2, 0x4d, 0x48, 0xb7, 0xb6, 0x49, 0xb4, 0x4b, 0x4a, 0xb5,
00035 0xa0, 0x5f, 0x5e, 0xa1, 0x5c, 0xa3, 0xa2, 0x5d, 0x58, 0xa7, 0xa6, 0x59, 0xa4, 0x5b, 0x5a, 0xa5,
00036 0x50, 0xaf, 0xae, 0x51, 0xac, 0x53, 0x52, 0xad, 0xa8, 0x57, 0x56, 0xa9, 0x54, 0xab, 0xaa, 0x55};
00037 
00038 uint32_t data[8]; // 24-bit audio in 
00039 uint32_t adat[8]; // raw ADAT frame
00040 uint32_t adat_nrz[8]; // NRZI encoded ADAT frame
00041 uint32_t dec_nrz[8]; // NRZI decoded ADAT frame
00042 uint32_t adec[8]; // audio decoded frame
00043 
00044 DigitalIn pb(USER_BUTTON);
00045 DigitalOut myled(LED1);
00046 
00047 // To display 32-bit binary data
00048 const char *byte_to_binary(int x)
00049 {
00050     static char b[33];
00051     b[32] = '\0';
00052 
00053     int z;
00054     for (z=0;z<32;z++)
00055     {
00056         b[z] = 48 + ( (x & (1<<(31-z))) != 0); 
00057     }
00058 
00059     return b;
00060 }
00061 
00062 
00063 // Right rotation
00064 inline uint32_t rorn (uint32_t x, uint32_t n)
00065 {
00066   return ((x)>>n) | ((x)<<(32-n));
00067 }
00068 
00069 // 1-bit right rotation
00070 inline void ror1(uint32_t* x)
00071 {
00072   *x = ((*x)>>1) | ((*x)<<(31));
00073 }
00074 
00075 
00076 inline uint32_t adat2audio(uint32_t x)
00077 {
00078 
00079     uint32_t R = x&0xF;
00080     R |= ( (x>>1) & 0xF0);    
00081     R |= ( (x>>2) & 0xF00);   
00082     R |= ( (x>>3) & 0xF000);    
00083     R |= ( (x>>4) & 0xF0000);    
00084     R |= ( (x>>5) & 0xF00000);
00085 
00086     return R;    
00087 }
00088 
00089 inline uint32_t audio2adat(uint32_t x)
00090 {
00091     uint32_t R = 0x02108421;
00092     R |= ( (x << 1) & 0x1E );
00093     R |= ( (x << 2) & 0x3c0 );
00094     R |= ( (x << 3) & 0x7800 );
00095     R |= ( (x << 4) & 0xf0000 );
00096     R |= ( (x << 5) & 0x1E00000 );
00097     R |= ( (x << 6) & 0x3c000000 );
00098     return R;
00099 }
00100 
00101 inline void adat_enc(uint32_t* in, uint32_t* out)
00102 {
00103     uint32_t R0, R1;
00104     R0 = audio2adat(in[0]);
00105     R1 = audio2adat(in[1]);
00106     out[0] = R0 | (R1 << 30);
00107     R0 = audio2adat(in[2]);
00108     out[1] = (R0 << 28) | (R1 >> 2);
00109     R1 = audio2adat(in[3]);
00110     out[2] = (R0 >> 4) | (R1 << 26);
00111     R0 = audio2adat(in[4]);
00112     out[3] = (R0 << 24) | (R1 >> 6);
00113     R1 = audio2adat(in[5]);
00114     out[4] = (R0 >> 8) | (R1 << 22);
00115     R0 = audio2adat(in[6]);
00116     out[5] = (R0 << 20) | (R1 >> 10);
00117     R1 = audio2adat(in[7]);
00118     out[6] = (R0 >> 12) | (R1 << 18);    
00119     out[7] = 0x08010000 | (R1 >> 14);
00120 }
00121 
00122 inline void adat_dec(uint32_t* in, uint32_t* out)
00123 {
00124     uint32_t R0, R1;
00125     R0 = in[0];
00126     R1 = in[1];
00127     out[0] = adat2audio(R0 >> 1);
00128     out[1] = adat2audio( (R0 >> 31) | (R1 << 1) ); 
00129     R0 = in[2];       
00130     out[2] = adat2audio( (R1 >> 29) | (R0 << 3) );   
00131     R1 = in[3];
00132     out[3] = adat2audio( (R0 >> 27) | (R1 << 5) );        
00133     R0 = in[4];       
00134     out[4] = adat2audio( (R1 >> 25) | (R0 << 7) );   
00135     R1 = in[5];
00136     out[5] = adat2audio( (R0 >> 23) | (R1 << 9) );        
00137     R0 = in[6];       
00138     out[6] = adat2audio( (R1 >> 21) | (R0 << 11) );   
00139     R1 = in[7];
00140     out[7] = adat2audio( (R0 >> 19) | (R1 << 13) );        
00141 }
00142 
00143 
00144 inline void nrz_enc(uint32_t* in, uint32_t* out)
00145 {
00146     static char last_bit = 0;
00147     for (int i = 0; i < 8; i++)
00148     {
00149         register uint32_t R = 0;
00150         uint32_t x = in[i]; 
00151         unsigned char c;
00152         for (int j = 0; j < 4; j++)
00153         {
00154             c = lut[(unsigned char)(x >> (j*8))];
00155 
00156             c = last_bit ? ~c : c;
00157            last_bit = c >> 7;
00158             R = rorn(R | c, 8);
00159         }
00160         out[i] = R;
00161     }   
00162 }
00163 
00164 inline void nrz_dec(uint32_t* in, uint32_t* out)
00165 {
00166     static char dec_last_bit = 0;
00167      for (int i = 0; i < 8; i++)
00168     {
00169         uint32_t x = in[i]; 
00170         out[i] = x ^ ( (x << 1) | dec_last_bit );
00171         dec_last_bit = x >> 31;
00172     }      
00173 }
00174 
00175 
00176 
00177 
00178 int main() {
00179     
00180     Serial pc(USBTX, USBRX);
00181     pc.baud(115200);
00182     
00183     for (int i = 0; i < 8; i++)    
00184     {
00185         data[i] = 0x00042184 + (i << 20);
00186     }
00187     
00188     uint32_t nframes = 480000; // 10s real time data
00189     gprintf("#VStarting encoding %Y ADAT frames\n", int(nframes));  
00190     t.start();
00191     for (int j = 0; j < nframes; j++)
00192     {
00193         if (pb) // so that the compiler cannot preprocess anything
00194         {
00195             for (int i = 0; i < 8; i++)    
00196             {
00197                 data[i] = (data[i] - i) &0xffffff;//make it recursive (makes really sure the compiler won't attempt to preprocess anything)
00198             }
00199 
00200         }
00201         myled = pb;   
00202           
00203         adat_enc(data, adat);     
00204         nrz_enc(adat, adat_nrz);
00205         nrz_dec(adat_nrz, dec_nrz);
00206         adat_dec(dec_nrz, adec);    
00207     }
00208     
00209     
00210     t.stop();
00211     std::stringstream toto;
00212     toto << t.read();
00213     gprintf("The time taken was %f seconds\n", toto.str());
00214        for (int i = 0; i < 8; i++)    
00215     {
00216         printf("data[%d] = %s\n", i, byte_to_binary(data[i]));
00217     }   
00218        for (int i = 0; i < 8; i++)    
00219     {
00220         printf("adat[%d] = %s\n", i, byte_to_binary(adat[i]));
00221     }
00222         for (int i = 0; i < 8; i++)    
00223     {
00224         printf("adat_nrz[%d] = %s\n", i, byte_to_binary(adat_nrz[i]));
00225     }   
00226         for (int i = 0; i < 8; i++)    
00227     {
00228         printf("dec_nrz[%d] = %s\n", i, byte_to_binary(dec_nrz[i]));
00229     }   
00230         for (int i = 0; i < 8; i++)    
00231     {
00232         printf("adec[%d] = %s\n", i, byte_to_binary(adec[i]));
00233     }   
00234     
00235     
00236     
00237     
00238     
00239 }
00240  
00241  
00242