Hola

Tengo una Teensy 4.1 enviando datos al puerto paralelo (14 Bits) de un DAC (DAC904) el cual requiere una señal de reloj con un flanco de subida (HIGH) para transferir los datos de la Teensy al DAC, dicha señal de reloj debe inmediatamente volver a (LOW) para encontrarse lista para la siguiente muestra.
La Teensy 4.1 la tengo sometida a 1 GHz de reloj, la idea es desarrollar una rutina que para este ejemplo debe crear una señal triangular a la salida del DAC (14 Bits con un total de 16384 niveles de tensión).

Click image for larger version. 

Name:	IMG_20200914_004729.jpg 
Views:	4 
Size:	101.3 KB 
ID:	21727

Actualmente con el código que expongo más adelante, el cual se resume en un buche de subida de rampa y un bucle de bajada de rampa (simplificado en lo siguiente):

//RAMPA DE SUBIDA
ValorDAC = InicioDAC;
while (ValorDAC <= FinalDAC)
{
GPIO6_DR = (ValorDAC << 18); //ASIGNA VALOR AL REGISTRO PUERTO PARALELO GPIO6 (16 BITS, 14 BITS DAC)
digitalWriteFast(0,HIGH); //CLOCK DAC904 = 1 //Memoriza Valor con flanco subida
digitalWriteFast(0,LOW); //CLOCK DAC904 = 0 //Retorna Clock a LOW
ValorDAC = (ValorDAC + IncrementoDAC);
}

//RAMPA DE BAJADA
ValorDAC = FinalDAC;
while (ValorDAC >= InicioDAC)
{
GPIO6_DR = (ValorDAC << 18); //ASIGNA VALOR AL REGISTRO PUERTO PARALELO GPIO6 (16 BITS, 14 BITS DAC)
digitalWriteFast(0,HIGH); //CLOCK DAC904 = 1 //Memoriza Valor con flanco subida
digitalWriteFast(0,LOW); //CLOCK DAC904 = 0 //Retorna Clock a LOW
ValorDAC = (ValorDAC - DecrementoDAC);
}




Queda simplificado en tres sentencias que se ejecutan en cada muestra:

GPIO6_DR = (ValorDAC << 18);
digitalWriteFast(0,HIGH);
digitalWriteFast(0,LOW);

Estas tres sentencias consumen (CLOCK CPU 1 GHz) el tiempo de 2 nS cada una, un total de 6 nS, lo que implica que para los 16384 niveles de tensión de salida del DAC la velocidad de la rampa (es de 100 microSegundos), entiendo que tengo la Teensy al límite y que las sentencias son de difícil optimización.

Hace muchos años trabaje con microprocesadores y microcontroladores en assembly series INTEL y de MICROCHIP, pero actualmente tengo bastante olvidado dicho tema, ya que mi enfoque del proyecto se encuentra en otro aspecto. Entiendo que esas tres sentencias podrían optimizarse de alguna forma, ya sea las tres en bloque o por los menos las dos últimas (subir y bajar un puerto rapidamente), de tal forma que de los 6 nS se pudiera pasar a 5 o 4 nS y de esa forma aumentar la velocidad de la rampa.

Mi consulta consiste en si a alguien se le ocurre como reducir el tiempo de dichas sentencias, sea con assembly online o de alguna otra forma agradecería enormemente su propuesta.

Adjunto código completo del ejemplo que pretendo:

#include <Arduino.h>
#if defined(__IMXRT1062__)
extern "C" uint32_t set_arm_clock(uint32_t frequency);
#endif

void FW_Barrido(int InicioDAC, int FinalDAC, int IncrementoDAC, int DecrementoDAC, int NCiclosBarrido, uint32_t ClockCPU)
{
int ValorDAC;
int ValorNCiclos;
set_arm_clock(ClockCPU);
digitalWrite(0, LOW); //CLOCK DAC904 =0
ValorNCiclos = 1;
while (ValorNCiclos <= NCiclosBarrido)
{

//RAMPA DE SUBIDA
ValorDAC = InicioDAC;
while (ValorDAC <= FinalDAC)
{
GPIO6_DR = (ValorDAC << 18); //ASIGNA VALOR AL REGISTRO PUERTO PARALELO GPIO6 (16 BITS, 14 BITS DAC)
digitalWriteFast(0,HIGH); //CLOCK DAC904 = 1 //Memoriza Valor con flanco subida
digitalWriteFast(0,LOW); //CLOCK DAC904 = 0 //Retorna Clock a LOW
ValorDAC = (ValorDAC + IncrementoDAC);
}

//RAMPA DE BAJADA
ValorDAC = FinalDAC;
while (ValorDAC >= InicioDAC)
{
GPIO6_DR = (ValorDAC << 18); //ASIGNA VALOR AL REGISTRO PUERTO PARALELO GPIO6 (16 BITS, 14 BITS DAC)
digitalWriteFast(0,HIGH); //CLOCK DAC904 = 1 //Memoriza Valor con flanco subida
digitalWriteFast(0,LOW); //CLOCK DAC904 = 0 //Retorna Clock a LOW
ValorDAC = (ValorDAC - DecrementoDAC);
}

ValorNCiclos++;
}
}

void setup()
{
pinMode(1, OUTPUT); //GPIO6-BIT2 SIN ASIGNAR FUNCION
pinMode(0, OUTPUT); //GPIO6-BIT3 CLOCK DAC904 14 BITS (FLANCO DE SUBIDA)

pinMode(19, OUTPUT); //GPIO6-BIT16 SIN ASIGNAR FUNCION
pinMode(18, OUTPUT); //GPIO6-BIT17 SIN ASIGNAR FUNCION
pinMode(14, OUTPUT); //GPIO6-BIT18 BIT B00 DAC904 14 BITS
pinMode(15, OUTPUT); //GPIO6-BIT19 BIT B01 DAC904 14 BITS
pinMode(40, OUTPUT); //GPIO6-BIT20 BIT B02 DAC904 14 BITS
pinMode(41, OUTPUT); //GPIO6-BIT21 BIT B03 DAC904 14 BITS
pinMode(17, OUTPUT); //GPIO6-BIT22 BIT B04 DAC904 14 BITS
pinMode(16, OUTPUT); //GPIO6-BIT23 BIT B05 DAC904 14 BITS
pinMode(22, OUTPUT); //GPIO6-BIT24 BIT B06 DAC904 14 BITS
pinMode(23, OUTPUT); //GPIO6-BIT25 BIT B07 DAC904 14 BITS
pinMode(20, OUTPUT); //GPIO6-BIT26 BIT B08 DAC904 14 BITS
pinMode(21, OUTPUT); //GPIO6-BIT27 BIT B09 DAC904 14 BITS
pinMode(38, OUTPUT); //GPIO6-BIT28 BIT B10 DAC904 14 BITS
pinMode(39, OUTPUT); //GPIO6-BIT29 BIT B11 DAC904 14 BITS
pinMode(26, OUTPUT); //GPIO6-BIT30 BIT B12 DAC904 14 BITS
pinMode(27, OUTPUT); //GPIO6-BIT31 BIT B13 DAC904 14 BITS
noInterrupts();
}

void loop()
{
bool ejecutar = true;
while (ejecutar)
{
//100 BARRIDOS RAMPA TRIANGULAR DE 16384 NIVELES PARA UN CLOCK_CPU DE 1 GHz
FW_Barrido(0, 16383, 1, 1, 100, 1000000000);
}
}