/* * Fichier pour travaux pratiques * Universite de Toulouse * * --- rappel des bits de donnes du port parallele pour Audine * ordre : 87654321 * bit 1 : horloge V1 * bit 2 : horloge V2 * bit 3 : horloge H1 * bit 4 : horloge R (reset) * bit 5 : horloge CL (clamp) * bit 6 : horloge Start Convert (CAN) * bit 7 : horloge Select Byte (CAN) * bit 8 : horloge Select Nibble * */ // https://raspberry-projects.com/pi/programming-in-c/io-pins/bcm2835-by-mike-mccauley // http://www.airspayce.com/mikem/bcm2835/ // sudo chown user:user /dev/gpiomem // Dans CodeBlocks, Menu Settings -> Compiler Settings, tab Other compiler options: Add -lbcm2835 // spyder : https://stackoverflow.com/questions/72114520/error-when-starting-spyder-on-ubuntu-22-04 #include #include #include #include #include #define PHI_V1 RPI_BPLUS_GPIO_J8_11 #define PHI_V2 RPI_BPLUS_GPIO_J8_13 #define PHI_H1 RPI_BPLUS_GPIO_J8_15 #define PHI_R RPI_BPLUS_GPIO_J8_16 #define PHI_CL RPI_BPLUS_GPIO_J8_18 #define PHI_SC RPI_BPLUS_GPIO_J8_22 #define PHI_SB RPI_BPLUS_GPIO_J8_32 #define PHI_SN RPI_BPLUS_GPIO_J8_36 #define BIT_0 RPI_BPLUS_GPIO_J8_29 #define BIT_1 RPI_BPLUS_GPIO_J8_31 #define BIT_2 RPI_BPLUS_GPIO_J8_33 #define BIT_3 RPI_BPLUS_GPIO_J8_35 #define DELAY RPI_BPLUS_GPIO_J8_40 #define LEVEL_HIGH 0 #define LEVEL_LOW 1 struct camprop { /* --- parametres standards, ne pas changer --- */ char msg[2048]; float exptime; int binx, biny; int x1, y1, x2, y2; int w, h; double celldimx; double celldimy; int overscanindex; int nb_deadbeginphotox; int nb_deadendphotox; int nb_deadbeginphotoy; int nb_deadendphotoy; int nb_photox; int nb_photoy; unsigned short *p; /* --- pour l'amplificateur des Kaf-401 --- */ int ampliindex; int nbampliclean; timespec t1; timespec t2; }; int cmdAudineAcqNormal(struct camprop *cam); static int tp_fast_vidage(struct camprop *cam); static int tp_read_win(struct camprop *cam); static void libcam_sleep(float us); static int tp_zi_zh(struct camprop *cam); static int tp_read_pel_fast2(struct camprop *cam); int tp_fast_line(struct camprop *cam); /* * Attente en micro-secondes. */ void libcam_sleep(float us) { int i,n; n = (int)(us*10); for (i=0; iexptime)); /* =============================================== */ /* === Etape de lecture de la matrice CCD === */ /* =============================================== */ /* Parametres de dimensions pour allouer le pointeur image */ cam->w = cam->nb_photox / cam->binx; cam->h = cam->nb_photoy / cam->biny; /* Allocation memoire du pointeur image */ cam->p = (unsigned short *) calloc(cam->w*cam->h, sizeof(unsigned short)); /* Lecture et num�risation de l'image vers le pointeur p */ tp_read_win(cam); return 0; } /* fast_vidage(struct camprop *cam) -- Vidage rapide de la matrice. Le decalage des lignes s'effectue ici par groupe de 20. C'est le seul parametre a regler ici. */ int tp_fast_vidage(struct camprop *cam) { int i, j; int imax, jmax, decaligne; /* Nombre total de photocellules dans le registre horizontal. */ imax = cam->nb_photox + cam->nb_deadbeginphotox + cam->nb_deadendphotox; /* Nombre total de photocellules dans une colonne de la matrice. */ jmax = cam->nb_photoy + cam->nb_deadbeginphotoy + cam->nb_deadendphotoy; /* Nombre de lignes decalees a chaque boucle sur l'axe vertical. */ decaligne = 20; /* Nombre total de boucles sur l'axe vertical. */ jmax = (int) ceil (1. * jmax / decaligne) ; /* Boucle sur les paquets de lignes. */ for (j = 0; j < jmax; j++) { /* Decalage d'un paquet de 20 lignes. */ for (i = 0; i < decaligne; i++) { tp_zi_zh(cam); } /* Lecture du registre horizontal sans reset */ for (i = 0; i < imax; i++) { tp_read_pel_fast2(cam); } } return 0; } /* tp_zi_zh(struct camprop *cam) -- Decalage vertical de toutes les lignes d'un cran vers le bas. La premiere ligne du bas est donc transferee dans le registre horizontal. */ int tp_zi_zh(struct camprop *cam) { float tphiV=2.0; float tphiHS=1.0; // --- bcm2835_gpio_write (PHI_V1, LEVEL_HIGH) ; libcam_sleep(tphiV); bcm2835_gpio_write (PHI_V1, LEVEL_LOW) ; bcm2835_gpio_write (PHI_V2, LEVEL_HIGH) ; libcam_sleep(tphiV); bcm2835_gpio_write (PHI_V1, LEVEL_HIGH) ; bcm2835_gpio_write (PHI_V2, LEVEL_LOW) ; libcam_sleep(tphiV); bcm2835_gpio_write (PHI_V1, LEVEL_LOW) ; libcam_sleep(tphiHS); return 0; } /* tp_read_pel_fast2(struct camprop *cam) -- Lecture rapide d'un pixel : decalage du registre horizontal sans Reset, mais sans lecture du CAN, */ int tp_read_pel_fast2(struct camprop *cam) { float tphiPIX=0.25; // --- bcm2835_gpio_write (PHI_H1, LEVEL_LOW) ; libcam_sleep(tphiPIX); bcm2835_gpio_write (PHI_H1, LEVEL_HIGH) ; libcam_sleep(tphiPIX); return 0; } /* tp_read_pel_fast(struct camprop *cam) -- Lecture rapide d'un pixel : decalage du registre horizontal avec Reset, mais sans lecture du CAN, */ int tp_read_pel_fast(struct camprop *cam) { float tphiPIX=0.25; float tphiR=0.020; // --- bcm2835_gpio_write (PHI_R, LEVEL_HIGH) ; libcam_sleep(tphiR); bcm2835_gpio_write (PHI_R, LEVEL_LOW) ; libcam_sleep(tphiR); bcm2835_gpio_write (PHI_H1, LEVEL_LOW) ; libcam_sleep(tphiPIX); bcm2835_gpio_write (PHI_H1, LEVEL_HIGH) ; libcam_sleep(tphiPIX); return 0; } /* tp_fast_line_() -- Lecture rapide du registre horizontal, avec la fonction read_pel_fast. */ int tp_fast_line(struct camprop *cam) { int i, imax; /* Nombre total de photocellules dans le registre horizontal. */ imax = cam->nb_photox + cam->nb_deadbeginphotox + cam->nb_deadendphotox; for (i = 0; i < imax; i++) { tp_read_pel_fast(cam); } return 0; } int tp_read_win(struct camprop *cam) { int i, j; int k, l; int imax, jmax; int cx1, cx2, cy1; unsigned short buffer[2048]; int x; /* dimensions de l'image a digitaliser */ imax = cam->w; jmax = cam->h; /* nombre de colonnes de debut a ne pas digitaliser */ cx1 = cam->nb_deadbeginphotox; /* nombre de colonnes de fin a ne pas digitaliser */ cx2 = cam->nb_deadendphotox; /* nombre de lignes de debut a ne pas digitaliser */ cy1 = cam->nb_deadbeginphotoy; /* On supprime les cy1 premieres lignes */ for (i = 0; i < cy1; i++) { tp_zi_zh(cam); } /* On nettoie le registre horizontal */ for (i = 0; i < 1; i++) { tp_fast_line(cam); } /* boucle sur l'horloge verticale (transfert) */ for (i = 0; i < jmax; i++) { /* boucle de binning vertical */ for (k = 0; k < cam->biny; k++) { tp_zi_zh(cam); } /* On retire les cx1 premiers pixels avec reset */ for (j = 0; j < cx1; j++) { tp_read_pel_fast(cam); } /* boucle sur l'horloge horizontale (registre de sortie) */ for (j = 0; j < imax; j++) { float tphiR=0.020; float tRef1=4.0; float tRef2=1.0; float tRef3=1.0; float tphiPIX=0.25; float tVid1=4.0; // palier de reset bcm2835_gpio_write (PHI_R, LEVEL_HIGH) ; bcm2835_gpio_write (PHI_H1, LEVEL_LOW) ; libcam_sleep(tphiR); bcm2835_gpio_write (PHI_R, LEVEL_LOW) ; libcam_sleep(tphiR); // palier de reference libcam_sleep(tRef1); bcm2835_gpio_write (PHI_CL, LEVEL_HIGH) ; libcam_sleep(tRef2); bcm2835_gpio_write (PHI_CL, LEVEL_LOW) ; libcam_sleep(tRef3); /* boucle de binning horizontal */ for (l = 0; l < cam->binx; l++) { bcm2835_gpio_write (PHI_H1, LEVEL_LOW) ; libcam_sleep(tphiPIX); bcm2835_gpio_write (PHI_H1, LEVEL_HIGH) ; libcam_sleep(tphiPIX); } // palier video libcam_sleep(tVid1); bcm2835_gpio_write (PHI_SC, LEVEL_HIGH) ; // -- recupere le nibble _ _ _ _ _ _ _ _ _ _ _ _ 3 2 1 0 // SB = Select Byte <---- SB=1 ----> <---- SB=0 ----> // SN = Select Nibble bcm2835_gpio_write (PHI_SB, LEVEL_LOW) ; bcm2835_gpio_write (PHI_SN, LEVEL_LOW) ; x = (int)bcm2835_gpio_lev(BIT_0); x += (int)bcm2835_gpio_lev(BIT_1) << 1; x += (int)bcm2835_gpio_lev(BIT_2) << 2; x += (int)bcm2835_gpio_lev(BIT_3) << 3; // -- recupere le nibble _ _ _ _ _ _ _ _ 3 2 1 0 _ _ _ _ bcm2835_gpio_write (PHI_SB, LEVEL_LOW) ; bcm2835_gpio_write (PHI_SN, LEVEL_HIGH) ; x += (int)bcm2835_gpio_lev(BIT_0) << 4; x += (int)bcm2835_gpio_lev(BIT_1) << 5; x += (int)bcm2835_gpio_lev(BIT_2) << 6; x += (int)bcm2835_gpio_lev(BIT_3) << 7; // -- recupere le nibble _ _ _ _ 3 2 1 0 _ _ _ _ _ _ _ _ bcm2835_gpio_write (PHI_SB, LEVEL_HIGH) ; bcm2835_gpio_write (PHI_SN, LEVEL_LOW) ; x += (int)bcm2835_gpio_lev(BIT_0) << 8; x += (int)bcm2835_gpio_lev(BIT_1) << 9; x += (int)bcm2835_gpio_lev(BIT_2) << 10; x += (int)bcm2835_gpio_lev(BIT_3) << 11; // -- recupere le nibble 3 2 1 0 _ _ _ _ _ _ _ _ _ _ _ _ bcm2835_gpio_write (PHI_SB, LEVEL_HIGH) ; bcm2835_gpio_write (PHI_SN, LEVEL_HIGH) ; x += (int)bcm2835_gpio_lev(BIT_0) << 12; x += (int)bcm2835_gpio_lev(BIT_1) << 13; x += (int)bcm2835_gpio_lev(BIT_2) << 14; x += (int)bcm2835_gpio_lev(BIT_3) << 15; // -- remises au niveaux bas bcm2835_gpio_write (PHI_SC, LEVEL_LOW) ; bcm2835_gpio_write (PHI_SB, LEVEL_LOW) ; bcm2835_gpio_write (PHI_SN, LEVEL_LOW) ; if (x > 32767) { x = 32767; } /* Stockage dans un buffer dans la meme page mem */ buffer[j] = (unsigned short) x; } /* On retire cx2 pixels a la fin */ for (j = 0; j < cx2; j++) { tp_read_pel_fast(cam); } /* On transfere le tableau vers la matrice image */ if (i != 0) { cam->p[(i - 1) * imax] = buffer[0]; } for (j = 1; j < imax; j++) { cam->p[(i + 1) * imax - j] = buffer[j]; } } return 0; } void mc_savefits(struct camprop *cam, char *filename) { FILE *f; char line[1024],car; float value0; char *cars0; int k,k0; long one= 1; int big_endian; f=fopen(filename,"wb"); strcpy(line,"SIMPLE = T / file does conform to FITS standard "); fwrite(line,80,sizeof(char),f); strcpy(line,"BITPIX = 16 / number of bits per data pixel "); fwrite(line,80,sizeof(char),f); strcpy(line,"NAXIS = 2 / number of data axes "); fwrite(line,80,sizeof(char),f); sprintf(line,"NAXIS1 = %3d / length of data axis 1 ",cam->w); fwrite(line,80,sizeof(char),f); sprintf(line,"NAXIS2 = %3d / length of data axis 2 ",cam->h); fwrite(line,80,sizeof(char),f); strcpy(line,"BZERO = 32768 / uint16 "); fwrite(line,80,sizeof(char),f); strcpy(line,"BSCALE = 1 / uint16 "); fwrite(line,80,sizeof(char),f); k0=9; strcpy(line,"END "); fwrite(line,80,sizeof(char),f); strcpy(line," "); for (k=k0;k<=36;k++) { fwrite(line,80,sizeof(char),f); } /* byte order test */ if (!(*((char *)(&one)))) { big_endian=1; } else { big_endian=0; } /* write data */ for (k=0;kh*cam->w;k++) { value0=cam->p[k]; // 32=4*8bits if (big_endian==0) { cars0=(char*)&value0; car=cars0[0]; cars0[0]=cars0[1]; cars0[1]=car; } fwrite(&value0,1,sizeof(unsigned short),f); } int n= (cam->h*cam->w) % 2880; //printf("big_endian=%d n=%d",big_endian, n); value0=(float)0.; for (k=0;k