Pour afficher une "frame", je dois afficher 16 "layers" de 256 bits. Pour afficher un layer je dois "pusher" les bits un à un en série et ensuite déclencher la recopie sur les sorties de mes cartes.
Si on vise un framerate de 25 fps alors il faut faire 25*16=400 layers par seconde soit 102400 pushs par seconde sur le port.
J'ai mis le code de push d'un layer dans une interruption. Pour afficher à 25fps, je dois l'exécuter 400 fois par seconde.
J'utilise la librairie suivante pour le timer : http://playground.arduino.cc/Code/Timer1
La valeur est en µs, pour tenir mon framerate je dois donc descendre à 2500µs pour du 25fps ou au moins 3500 si on vise le 18fps.
Or, et c'est bien là mon soucis, en dessous de 5000~5500µs de période, y'a plus aucun changement (le code de la loop principale ne s'exécute plus comme il faut). Et je peux vous assurer qu'à 10~12 fps on le voit le clignottement...
Voici mon code si vous voyez si un truc "énorme" m'aurait échappé...
#include "TimerOne.h"
char video_buffer[]={LOW, LOW, LOW, LOW, LOW, LOW, HIGH, HIGH, HIGH, HIGH, LOW, LOW, LOW, LOW, LOW, LOW,
LOW, LOW, LOW, LOW, HIGH, HIGH, LOW, LOW, LOW, LOW, HIGH, HIGH, LOW, LOW, LOW, LOW,
LOW, LOW, HIGH, HIGH, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, HIGH, HIGH, LOW, LOW,
LOW, LOW, HIGH, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, HIGH, LOW, LOW,
LOW, HIGH, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, HIGH, LOW,
LOW, HIGH, LOW, LOW, HIGH, HIGH, LOW, LOW, LOW, LOW, HIGH, HIGH, LOW, LOW, HIGH, LOW,
HIGH, LOW, LOW, LOW, HIGH, HIGH, LOW, LOW, LOW, LOW, HIGH, HIGH, LOW, LOW, LOW, HIGH,
HIGH, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, HIGH,
HIGH, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, HIGH,
HIGH, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, HIGH,
LOW, HIGH, LOW, LOW, HIGH, LOW, LOW, LOW, LOW, LOW, LOW, HIGH, LOW, LOW, HIGH, LOW,
LOW, HIGH, LOW, LOW, LOW, HIGH, LOW, LOW, LOW, LOW, HIGH, LOW, LOW, LOW, HIGH, LOW,
LOW, LOW, HIGH, LOW, LOW, LOW, HIGH, HIGH, HIGH, HIGH, LOW, LOW, LOW, HIGH, LOW, LOW,
LOW, LOW, HIGH, HIGH, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, HIGH, HIGH, LOW, LOW,
LOW, LOW, LOW, LOW, HIGH, HIGH, LOW, LOW, LOW, LOW, HIGH, HIGH, LOW, LOW, LOW, LOW,
LOW, LOW, LOW, LOW, LOW, LOW, HIGH, HIGH, HIGH, HIGH, LOW, LOW, LOW, LOW, LOW, LOW};
// :)
char sprite[]={LOW, LOW, LOW, LOW, LOW, LOW, HIGH, HIGH, HIGH, HIGH, LOW, LOW, LOW, LOW, LOW, LOW,
LOW, LOW, LOW, LOW, HIGH, HIGH, LOW, LOW, LOW, LOW, HIGH, HIGH, LOW, LOW, LOW, LOW,
LOW, LOW, HIGH, HIGH, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, HIGH, HIGH, LOW, LOW,
LOW, LOW, HIGH, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, HIGH, LOW, LOW,
LOW, HIGH, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, HIGH, LOW,
LOW, HIGH, LOW, LOW, HIGH, HIGH, LOW, LOW, LOW, LOW, HIGH, HIGH, LOW, LOW, HIGH, LOW,
HIGH, LOW, LOW, LOW, HIGH, HIGH, LOW, LOW, LOW, LOW, HIGH, HIGH, LOW, LOW, LOW, HIGH,
HIGH, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, HIGH,
HIGH, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, HIGH,
HIGH, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, HIGH,
LOW, HIGH, LOW, LOW, HIGH, LOW, LOW, LOW, LOW, LOW, LOW, HIGH, LOW, LOW, HIGH, LOW,
LOW, HIGH, LOW, LOW, LOW, HIGH, LOW, LOW, LOW, LOW, HIGH, LOW, LOW, LOW, HIGH, LOW,
LOW, LOW, HIGH, LOW, LOW, LOW, HIGH, HIGH, HIGH, HIGH, LOW, LOW, LOW, HIGH, LOW, LOW,
LOW, LOW, HIGH, HIGH, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, HIGH, HIGH, LOW, LOW,
LOW, LOW, LOW, LOW, HIGH, HIGH, LOW, LOW, LOW, LOW, HIGH, HIGH, LOW, LOW, LOW, LOW,
LOW, LOW, LOW, LOW, LOW, LOW, HIGH, HIGH, HIGH, HIGH, LOW, LOW, LOW, LOW, LOW, LOW};
// wolf
char sprite2[]={LOW, HIGH, HIGH, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, HIGH, HIGH, LOW,
LOW, HIGH, LOW, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, LOW, HIGH, LOW,
LOW, HIGH, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, HIGH, LOW,
LOW, HIGH, LOW, LOW, HIGH, LOW, LOW, LOW, LOW, LOW, LOW, HIGH, LOW, LOW, HIGH, LOW,
HIGH, HIGH, LOW, LOW, HIGH, HIGH, LOW, LOW, LOW, LOW, HIGH, HIGH, LOW, LOW, HIGH, HIGH,
HIGH, LOW, LOW, LOW, LOW, LOW, HIGH, LOW, LOW, HIGH, LOW, LOW, LOW, LOW, LOW, HIGH,
HIGH, LOW, LOW, LOW, LOW, LOW, HIGH, LOW, LOW, HIGH, LOW, LOW, LOW, LOW, LOW, HIGH,
HIGH, LOW, LOW, LOW, LOW, LOW, HIGH, LOW, LOW, HIGH, LOW, LOW, LOW, LOW, LOW, HIGH,
HIGH, HIGH, LOW, LOW, LOW, LOW, HIGH, LOW, LOW, HIGH, LOW, LOW, LOW, LOW, HIGH, HIGH,
LOW, LOW, HIGH, LOW, LOW, LOW, HIGH, HIGH, HIGH, HIGH, LOW, LOW, LOW, HIGH, LOW, LOW,
LOW, LOW, HIGH, LOW, LOW, LOW, HIGH, HIGH, HIGH, HIGH, LOW, LOW, LOW, HIGH, LOW, LOW,
LOW, LOW, HIGH, HIGH, HIGH, LOW, LOW, LOW, LOW, LOW, LOW, HIGH, HIGH, HIGH, LOW, LOW,
LOW, LOW, LOW, LOW, HIGH, LOW, LOW, LOW, LOW, LOW, LOW, HIGH, LOW, LOW, LOW, LOW,
LOW, LOW, LOW, LOW, HIGH, LOW, LOW, HIGH, HIGH, LOW, LOW, HIGH, LOW, LOW, LOW, LOW,
LOW, LOW, LOW, LOW, LOW, HIGH, HIGH, LOW, LOW, HIGH, HIGH, LOW, LOW, LOW, LOW, LOW};
int frame=0;
int couche_vbl=0;
int nb_out=0;
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin 13 as an output.
pinMode(53, OUTPUT); // Data IN
pinMode(52, OUTPUT); // Latch
pinMode(51, INPUT); // Data OUT
pinMode(50, OUTPUT); // Clk
pinMode(49, OUTPUT); // selcouche bit 3
pinMode(48, OUTPUT); // selcouche bit 2
pinMode(47, OUTPUT); // selcouche bit 1
pinMode(46, OUTPUT); // selcouche bit 0
pinMode(13, OUTPUT); // onboard led
selcouche(0);
//Autotest (comptage d'un cycle)
//init with 0
for (int i=0;i<4096; i++){
digitalWrite(53, LOW);
digitalWrite(50, LOW);
digitalWrite(50, HIGH);
}
//insert 1
digitalWrite(53, HIGH);
digitalWrite(50, LOW);
digitalWrite(50, HIGH);
nb_out=1;
//fill with 0 until 1 exits the loop
while (digitalRead(51)==LOW){
digitalWrite(53, LOW);
digitalWrite(50, LOW);
digitalWrite(50, HIGH);
nb_out++;
}
//init with 0
for (int i=0;i<nb_out; i++){
digitalWrite(53, LOW);
digitalWrite(50, LOW);
digitalWrite(50, HIGH);
}
//DISPLAY
digitalWrite(52, HIGH);
digitalWrite(52, LOW);
digitalWrite(13, LOW);
Timer1.initialize(50000);
Timer1.attachInterrupt(VBL);
}
void selcouche(int couche){
switch(couche){
case 0:
digitalWrite(49, LOW);
digitalWrite(48, LOW);
digitalWrite(47, LOW);
digitalWrite(46, LOW);
break;
case 1:
digitalWrite(49, LOW);
digitalWrite(48, LOW);
digitalWrite(47, LOW);
digitalWrite(46, HIGH);
break;
case 2:
digitalWrite(49, LOW);
digitalWrite(48, LOW);
digitalWrite(47, HIGH);
digitalWrite(46, LOW);
break;
case 3:
digitalWrite(49, LOW);
digitalWrite(48, LOW);
digitalWrite(47, HIGH);
digitalWrite(46, HIGH);
break;
case 4:
digitalWrite(49, LOW);
digitalWrite(48, HIGH);
digitalWrite(47, LOW);
digitalWrite(46, LOW);
break;
case 5:
digitalWrite(49, LOW);
digitalWrite(48, HIGH);
digitalWrite(47, LOW);
digitalWrite(46, HIGH);
break;
case 6:
digitalWrite(49, LOW);
digitalWrite(48, HIGH);
digitalWrite(47, HIGH);
digitalWrite(46, LOW);
break;
case 7:
digitalWrite(49, LOW);
digitalWrite(48, HIGH);
digitalWrite(47, HIGH);
digitalWrite(46, HIGH);
break;
case 8:
digitalWrite(49, HIGH);
digitalWrite(48, LOW);
digitalWrite(47, LOW);
digitalWrite(46, LOW);
break;
case 9:
digitalWrite(49, HIGH);
digitalWrite(48, LOW);
digitalWrite(47, LOW);
digitalWrite(46, HIGH);
break;
case 10:
digitalWrite(49, HIGH);
digitalWrite(48, LOW);
digitalWrite(47, HIGH);
digitalWrite(46, LOW);
break;
case 11:
digitalWrite(49, HIGH);
digitalWrite(48, LOW);
digitalWrite(47, HIGH);
digitalWrite(46, HIGH);
break;
case 12:
digitalWrite(49, HIGH);
digitalWrite(48, HIGH);
digitalWrite(47, LOW);
digitalWrite(46, LOW);
break;
case 13:
digitalWrite(49, HIGH);
digitalWrite(48, HIGH);
digitalWrite(47, LOW);
digitalWrite(46, HIGH);
break;
case 14:
digitalWrite(49, HIGH);
digitalWrite(48, HIGH);
digitalWrite(47, HIGH);
digitalWrite(46, LOW);
break;
case 15:
digitalWrite(49, HIGH);
digitalWrite(48, HIGH);
digitalWrite(47, HIGH);
digitalWrite(46, HIGH);
break;
default:
digitalWrite(49, LOW);
digitalWrite(48, LOW);
digitalWrite(47, LOW);
digitalWrite(46, LOW);
}
}
// The callback of the timer1 (displays a layer)
void VBL(){
for (int i=0;i<nb_out; i++){
digitalWrite(53, video_buffer[i]);
digitalWrite(50, LOW);
digitalWrite(50, HIGH);
}
//DISPLAY
selcouche(couche_vbl);
digitalWrite(52, HIGH);
digitalWrite(52, LOW);
couche_vbl=(couche_vbl+1)&15;
}
// the loop function runs over and over again forever
void loop() {
if( frame==0){
frame=1;
memcpy(video_buffer, sprite,256);
}else{
frame=0;
memcpy(video_buffer, sprite2,256);
}
delay(1000);
}