7 | | - Les coordonnées x et y sont des nombres entiers signés de -127 à +127. |
8 | | - L'angle est |
| 7 | - Le circuit prend en entrée |
| 8 | - les coordonnées x_p et y_p qui sont des nombres entiers signés de -127 à +127. |
| 9 | - L'angle a_p est exprimé en radian et il est représenté par un nombre en virgule fixe **non** signé 3-7. |
| 10 | - À l'intérieur du circuit, c'est un nombre en virgule fixe 1-8-7. |
| 11 | - Mais à l'interface, j'ai choisi une représentation non signée 3-7 (port a_p) pour avoir des angles entre 0 et presque 8 radians. |
| 12 | La conversion se fait dans le circuit en recopiant les 10 bits de a_p dans les 10 bits de poids faible d'un registre de 16 bits représentant l'angle, puis en complétant avec des `0`à gauche. |
| 13 | C'est un choix pour réduire le nombre de broches, mais vous pouvez faire un choix plus "propre" en codant l'angle en 1-3-7 et faire une conversion avec extension du signe. |
| 14 | - le circuit reçoit aussi une horloge. |
| 15 | - Le circuit produit en sortie les coordonnées (nx_p, ny_p) du vecteur après rotation. |
| 16 | - Le protocole de communication en entrée et en sortie est FIFO. |
| 18 | {{{ |
| 19 | #!c |
| 20 | //----------------------------------------------------------------------------- |
| 21 | // Calcul des points d'un cercle par l'algorithme Cordic |
| 22 | //----------------------------------------------------------------------------- |
| 23 | // cossin : utilisation des fonctions cos et sin de la bibliothèque maths |
| 24 | // cordic : cordic en virgule fixe 8 chiffres après la virgules |
| 25 | //----------------------------------------------------------------------------- |
| 26 | #include <stdio.h> |
| 27 | #include <math.h> |
| 28 | |
| 29 | #ifndef M_PI |
| 30 | #define M_PI 3.14159265358979323846 |
| 31 | #endif |
| 32 | |
| 33 | void cossin(double a_p, char x_p, char y_p, char *nx_p, char *ny_p) |
| 34 | { |
| 35 | *nx_p = (char) (x_p * cos(a_p) - y_p * sin(a_p)); |
| 36 | *ny_p = (char) (x_p * sin(a_p) + y_p * cos(a_p)); |
| 37 | } |
| 38 | |
| 39 | short F_PI = (short)((M_PI) * (1<< 7)); |
| 40 | short ATAN[8] = { |
| 41 | 0x65, // ATAN(2^-0) |
| 42 | 0x3B, // ATAN(2^-1) |
| 43 | 0x1F, // ATAN(2^-2) |
| 44 | 0x10, // ATAN(2^-3) |
| 45 | 0x08, // ATAN(2^-4) |
| 46 | 0x04, // ATAN(2^-5) |
| 47 | 0x02, // ATAN(2^-6) |
| 48 | 0x01, // ATAN(2^-7) |
| 49 | }; |
| 50 | |
| 51 | void cordic(short a_p, char x_p, char y_p, char *nx_p, char *ny_p) |
| 52 | { |
| 53 | unsigned char i, q; |
| 54 | short a, x, y, dx, dy; |
| 55 | |
| 56 | // conversion en virgule fixe : 7 chiffres après la virgule |
| 57 | a = a_p; |
| 58 | x = x_p << 7; |
| 59 | y = y_p << 7; |
| 60 | |
| 61 | // normalisalion de l'angle pour être dans le premier quadrant |
| 62 | q = 0; |
| 63 | while (a >= F_PI/2) { |
| 64 | a = a - F_PI/2; |
| 65 | q = (q + 1) & 3; |
| 66 | } |
| 67 | |
| 68 | // rotation |
| 69 | for (i = 0; i <= 7; i++) { |
| 70 | dx = x >> i; |
| 71 | dy = y >> i; |
| 72 | if (a >= 0) { |
| 73 | x -= dy; |
| 74 | y += dx; |
| 75 | a -= ATAN[i]; |
| 76 | } else { |
| 77 | x += dy; |
| 78 | y -= dx; |
| 79 | a += ATAN[i]; |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | // produit du résultat par les cosinus des angles : K=0x4E=1001110 |
| 84 | x = ((x>>6) + (x>>5) + (x>>4) + (x>>1))>>7; |
| 85 | y = ((y>>6) + (y>>5) + (y>>4) + (y>>1))>>7; |
| 86 | |
| 87 | // placement du points dans le quadrant d'origine |
| 88 | switch (q) { |
| 89 | case 0: |
| 90 | dx = x; |
| 91 | dy = y; |
| 92 | break; |
| 93 | case 1: |
| 94 | dx = -y; |
| 95 | dy = x; |
| 96 | break; |
| 97 | case 2: |
| 98 | dx = -x; |
| 99 | dy = -y; |
| 100 | break; |
| 101 | case 3: |
| 102 | dx = y; |
| 103 | dy = -x; |
| 104 | break; |
| 105 | } |
| 106 | *nx_p = dx; |
| 107 | *ny_p = dy; |
| 108 | } |
| 109 | |
| 110 | int main() |
| 111 | { |
| 112 | FILE *f; |
| 113 | double t,K; |
| 114 | int i; |
| 115 | printf("PI/2 = %x %x\n", F_PI/2i, 128<<7); |
| 116 | for (i=0, t=1, K=1; i < 8; i++, t=t/2) { |
| 117 | printf("B_%d = 0x%x\n", i, (short)(round(atan(t)*(1<< 7)))); |
| 118 | K = K * cos (atan(t)); |
| 119 | } |
| 120 | printf("K = %g, 0x%x\n", K, (short)(round(K*(1<< 7)))); |
| 121 | |
| 122 | f = fopen("cossin.dat", "w"); |
| 123 | for (double a = 0; a <= M_PI * 2; a += 1. / 256) { |
| 124 | char nx_p; |
| 125 | char ny_p; |
| 126 | cossin(a, 127, 0, &nx_p, &ny_p); |
| 127 | fprintf(f, "%4d %4d\n", nx_p, ny_p); |
| 128 | } |
| 129 | fclose(f); |
| 130 | |
| 131 | f = fopen("cordic.dat", "w"); |
| 132 | for (short a = 0; a <= 2 * F_PI ; a += 1) { |
| 133 | char nx_p; |
| 134 | char ny_p; |
| 135 | cordic(a, 127, 0, &nx_p, &ny_p); |
| 136 | fprintf(f, "%4d %4d\n", nx_p, ny_p); |
| 137 | } |
| 138 | fclose(f); |
| 139 | |
| 140 | return 0; |
| 141 | } |
| 142 | }}} |
| 143 | |
| 144 | |
| 145 | |
| 146 | |