/* 45 iTTL_V0 *********************** created 2020 by Herve QUEVAL V0 - manage 45CL3 CL4 in TTL mode. to be run on Teensy 2.0 with no addon cards. In fact use a sCA3009 M1 interface with flash 45CL 3 or CL4. Analog input as follow FLASH_Mode 21 A0 Digital /DSLR_Sync 0 in DSLR_DATA 1 in/out DSLR_CLK 2 out /DSLR_Hshake 3 in /LED_OUT 20 out /FLASH_Sync 19 out /FLASH_Ready 18 in /AF_Asyst 17 out FLASH_Stop 167 out FLASH_Expo_OK 15 in /Test button 14 in /SW1 23 in selection TTL ou TTL BL */ //*********************** Debugging *************************************************************** //#define DEBUG 1 //#define DEBUG_ITTL 1 //#define DEBUG_ITTL1 1 // verbode mode of DEBUG_ITTL // #define DEBUG_ITTL2 1 // I-TTL Time out trace // #define DEBUG_DSLR_CMD 1 // #define DEBUG_FLASH 1 // #define DEBUG_FLASH_MODE 1 // ************ constants Used here to set pin numbers ******************************************** // DSLR interface const int DSLR_SYNC = 0; // in const int DSLR_DATA = 1; // in/out (out during frame transfer initiation or send capability or info ) const int DSLR_CLK = 2; // out const int DSLR_Hshake = 3; // in const int DSLR_CLK2 = 5; // in (out during HW init phase) // Flash Interface int FLASH_MODE_IN = A0; // analog input 21 const int LED_SCA = 20; // out const int FLASH_Sync = 19; // out const int FLASH_READY = 18; // in const int AF_ASSIST = 17; // out const int FLASH_Stop = 16; // out const int FLASH_Expo_OK = 15; // in //SCA interface (Led and test button const int TEST_BUTTON = 14; // in const int SW1 = 23; // in // test - Debugging interface - activ low const int TP1 = 6; // out Preflash const int TP2 = 7; // out Power cde const int TP3 = 8; // out Data aborted // Power conversion table // ---------------------- // Table to convert Nikon index 0x54.. 0XA8 to duration // Min and max Nikon index values obtained using Godox XA2/WA1 in manual 1/128.. 1/1 and SB900 Flash // in real life could receive smaller values than 0x54 // 0 if manual or A mode // 40 if TTL mode... int Flash_Duration_Long[86] = { // 85 elements - Offset 0x54 // 1/128 ... 1/1 - 1/12 IL increment // Index 0.. 84 50, 52, 54, 55, 57, 59, 61, 62, 64, 66, 68, 69, 71, 73, 76, 78, 80, 83, 85, 88, 90, 93, 95, 98, 100, 106, 111, 117, 122, 128, 133, 139, 144, 150, 155, 161, 169, 174, 180, 187, 194, 201, 208, 215, 222, 229, 236, 243, 250, 265, 277, 288, 300, 313, 320, 335, 345, 360, 370, 388, 405, 425, 450, 483, 510, 558, 600, 653, 710, 770, 835, 915, 1000, 1100, 1225, 1350, 1510, 1708, 1905, 2103, 2325, 2550, 2800, 3050, 3300 }; //ITTL answer message definition //---------------------------------------------------------------------------------------------- // use to SB900 message // A0 first and second byte and CRC are recalculated to report flash ready and selected Flash mode ( A, M, TTL) #define A0_LEN 22 // message len in byte minus commande byte and includes CRC #define A1_LEN 18 #define A2_LEN 46 byte MessageA0[A0_LEN+1] = { 3,1,0xC0,4,0,0,0x92,0x5E,0x30,0x4B,0,0xFF,0xFF,0,0,0,0,0,0,0,0,0x32}; byte MessageA1[A1_LEN+1] = { 1,1,5,2,8,7,0x81,0x78,0xB4,0x64,0x0A,0x4E,0xFF,0x3E,0x90,0x3E,0x90,0x1D}; byte MessageA2[A2_LEN+1] = { 3,5,0x6D,0x9B,0x90,0x86,0x80,0x7A,0x72,0x6A,0x65,0x5E,6,0x75,0x9E,0x94,0x8A,0x80, 0x77,0x6F,0x66,0x60,0x58,6,0x74,0x9E,0x95,0x8B,0x80,0x76,0x6F,0x66,0x60,0x59,4,0x5F, 0x96,0x8A,0x82,0x80,0x7E,0x79,0x71,0x6E,0x6A,0xFC }; //Nikon Flash ready code for A0 frame // bit 0 0 not ready 1 ready // bit 1 0 ack flash 1 normal no acl #define BIT_NIK_READY B00000001 #define BIT_NIK_NOACK B00000010 //Constantes ---------------- Protocole et Flash -------------------------------------------------------- #define TIME_OUT_DURATION 10 // Time Out protocol - duration in 0,1 sec #define TIME_OUT1_DURATION 400 // Time Out handshake - duration in 1 µSec Test give 200 µS limit... #define TEST_FLASH_DURATION 40 // Test flash duration in µS #define PRE_FLASH_DURATION 50 // Pre flash duration in µS #define PRE_FLASH30_DURATION 510 // Pre flash 30% duration in µS #define FLASH_ADJUST 4 // offset in the Power table to adjust exposure. 12 = +1 IL - positive value only. // variable globales ************************************************ // // DISABLE // DSLR OFF, STANDBY or SCA not connected. // WAIT // DSLR ON start nego begin frame // STANDBY // DSLR standby (protocole standby - already negotiated/sync) // READY // 1st pulse Handshake received - interface synchronized, read cde and decode // RECEIVED // Cde Received No time out - could process Cde. byte ITTL_FrameState; // I-TTL protocol frame state #define DISABLE 0 #define WAIT 1 #define STANDBY 2 #define READY 3 #define RECEIVED 4 byte ITTL_State; // I-TTL protocol frame state #define INACTIV 0 #define INIT 1 #define STARTED 2 #define ACTIV 3 byte d; // data lue byte n; // frame byte to read or send int p; // pointer in array byte b; // byte to send. byte Cde; // Cde lu byte Data_Direction; // indicate Data bus direction between tasks: cde decoder to data exchange #define IN 0 #define OUT 1 byte Crc; byte Flash_Power_Index; // information from i_TTL pwer cde. Nikon code received from DSLR int Flash_Duration; // flash duration corresponding to Flash Power Index received byte AF_Assist; byte Flash_NikMode; //Nikon Flash mode code for A0 frame #define NIK_TTLBL 1 #define NIK_TTL 2 #define NIK_AA 3 // Flash decide AA or A depending of info in B0 #define NIK_A 4 #define NIK_GN 5 #define NIK_M 6 #define NIK_RPT 7 byte Flash_Mode; // Metz Flash mode - internal for programm #define UNDEFINED 0 #define TTL 1 #define A 2 #define M 3 //uint8_t a0; // used by Class Analog int Analog_Mode; // used to process analog signal and detect Flash mode // seuil théorique avec R47K // Mode TTL 240 à 255 LSB // Mode A 330 (2.8) 505 ( 16) // Mode M 1023 #define Seuil_TTL 170 #define Seuil_A 290 #define Seuil_M 700 byte Flash_TestBlocked; //test button byte Flash_TestRequest; #define TEST_BLOCK_DURATION 4 byte Ack_requested; // set to 1 to send ack in A0 frame answer to request received in B0 byte PowerCommand_Context; // Context of Power : 1er byte data power cde #define DONOTPROCESS 0 // 0000 0000 #define ITTL_FLASH 0x10 // 0001 0000 #define ITTL_AEL 0XD0 // 1101 0000 #define BIT_FP B00001000 // xxxx 1sss sss indicate shutter speed to define FP duration byte Exposure_Correction; // exposure correction reveived from DSLR multiply by -2 byte FlashActivityLevel; // 00 if fully available FF not available. in the middle scale of usage... int T1; // Led timer byte T2; // Time volatile byte TimeOut1; // set to 2 if time out ; always 1 after Timer.start !! // for test +++++++++++++++++++++++ byte temp; //********************************************************************************************************************************* #include #include void setup() { // ******************************************************** initialisation ************************************** // setup DSLR Interface pin pinMode(DSLR_SYNC, INPUT_PULLUP); // in - internal + 220pF to GND pinMode(DSLR_DATA, INPUT_PULLUP); // in/out; PULLUP to avoid noise; at power up IN, always IN ; only out during Device identification and answer to DSLR request. pinMode(DSLR_CLK, INPUT); // output except during init. pinMode(DSLR_Hshake,INPUT); // in - external pull-down 10K pinMode(DSLR_CLK2, INPUT); // output during init. Data_Direction = IN; // setup Flash Interface pin pinMode(LED_SCA, OUTPUT); pinMode(FLASH_Sync, OUTPUT); pinMode(FLASH_READY, INPUT_PULLUP); pinMode(AF_ASSIST, OUTPUT); pinMode(FLASH_Stop, OUTPUT); pinMode(FLASH_Expo_OK, INPUT_PULLUP); pinMode(TEST_BUTTON, INPUT_PULLUP); // in with 0,1µF in parallel on contact. pinMode(SW1, INPUT_PULLUP); // in - external pull-up needed?? // init flash output interface digitalWrite(LED_SCA, LOW); // turn the SCA LED on during INIT digitalWrite(FLASH_Sync, HIGH); // Active low digitalWrite(AF_ASSIST, HIGH); // Active low digitalWrite(FLASH_Stop, LOW); // Active high // init and set Test pin pinMode(TP1, OUTPUT); digitalWrite(TP1, HIGH); pinMode(TP2, OUTPUT); digitalWrite(TP2, HIGH); pinMode(TP3, OUTPUT); digitalWrite(TP3, HIGH); // init Timer 3 use timer 3 to detect i-TTL protocol time-out Timer3.initialize(100000); // interrupt each 100ms Timer3.attachInterrupt(Time3Event); // init Timer 1 use timer 1 to detect i-TTL handshake time-out TimeOut1=0; Timer1.initialize(TIME_OUT1_DURATION); Timer1.attachInterrupt(Time1Event); Timer3.stop(); // will be started if syncronisation started Timer1.stop(); // will be started waiting Handshake // init context global variable ITTL_FrameState = DISABLE; ITTL_State = INACTIV; Flash_Duration = 50; // contexte Flash Mode Flash_Mode = UNDEFINED; Analog_Mode = 0; // contexte Test button Flash_TestRequest =0; Ack_requested=0; FlashActivityLevel=0; //fully available. #ifdef DEBUG delay(1000); // wait for ??? serial USB initialized ....... Serial.println("DEBUG ON"); #endif #ifdef DEBUG_FLASH Serial.println("DEBUG FLASH interface ON"); #endif #ifdef DEBUG_ITTL Serial.println("DEBUG I-TTL ON"); #endif delay(100); // sense clock line (like X2T GODOX) -------------------------------------- pinMode(DSLR_CLK2, OUTPUT); digitalWrite (DSLR_CLK2, HIGH); // obtain CLK +5V if not connected, +1,4V if connected to body delay(48); delayMicroseconds(500); if (digitalRead(DSLR_CLK) == LOW) { // sens CLK line #ifdef DEBUG_ITTL Serial.println("INIT - SCA connected"); #endif } else { #ifdef DEBUG_ITTL Serial.println("INIT - SCA not connected"); #endif pinMode(DSLR_CLK, OUTPUT); digitalWrite (DSLR_CLK, HIGH); pinMode(DSLR_CLK2, INPUT); // high Z delayMicroseconds(1500); digitalWrite (DSLR_CLK, LOW); } digitalWrite(LED_SCA, HIGH); // turn the SCA LED off // init led params T1=1600; T2=10; } //***************************************************************************************************** end Init ****************** // interupt 3 TimeOutEvent ---------------------------------- volatile byte TimeOut=0; // set to 1 if time out volatile byte TicCount=TIME_OUT_DURATION; //time ou in 0,1 sec void Time3Event(void){ if (TicCount==0) { TimeOut = 1; } else { TicCount--; } } void ArmTimeOut(void){ noInterrupts(); TicCount=TIME_OUT_DURATION; TimeOut=0; Timer3.start(); interrupts(); } // interupt 1 TimeOutEvent ---------------------------------- void Time1Event(void){ // TimeOut1 = 1; TimeOut1++; } void ArmTimeOut_1(void){ noInterrupts(); TimeOut1=0; Timer1.start(); interrupts(); } // convert power to duration ------ Power coded acording Nikon power level ; return flash duration in micro second using large table. int Power2Time(byte power) { int duration =0; if (power < 0x54) { // min power duration = Flash_Duration_Long[0]; } else if (power > 0xA8) { duration = Flash_Duration_Long[84]; // max power } else { duration = Flash_Duration_Long[power+(FLASH_ADJUST-0x54)]; // minus offset of the Nikon power cde code } return duration; } /* byte DSLR_ReadFreqMax() { //Generate clock and read data for test purpose byte val = 0; digitalWrite(DSLR_CLK, LOW); // mini pulse to see delay between call digitalWrite(DSLR_CLK, HIGH); delayMicroseconds(1); // 1, 39 µS until first low pulse for (byte offset = 0; offset < 8; offset++) { // loop to read the 8 bits val = val << 1; digitalWrite(DSLR_CLK, LOW); delayMicroseconds(1); // 1+0,44 µS digitalWrite(DSLR_CLK, HIGH); val |= digitalRead(DSLR_DATA) ; // constant delay 1,64 µS delayMicroseconds(1); } digitalWrite(DSLR_CLK, LOW); // mini pulse to see delay between call digitalWrite(DSLR_CLK, HIGH); return val; } */ byte DSLR_ReadByte() { // Generate clock and deserialize data from DSLR; byte val = 0; for (byte offset = 0; offset < 8; offset++) { // loop to read the 8 bits val = val >> 1 ; digitalWrite(DSLR_CLK, LOW); delayMicroseconds(16); digitalWrite(DSLR_CLK, HIGH); if (digitalRead(DSLR_DATA) == HIGH ) { val |= 0x80; } delayMicroseconds(16); } return val; } void DSLR_OpenDataOutput() { // activate Serial Data Out pinMode(DSLR_DATA, OUTPUT); digitalWrite(DSLR_DATA,LOW); } void DSLR_CloseDataOutput() { // Close serial Data Out pinMode(DSLR_DATA, INPUT_PULLUP); } void DSLR_WriteByte(byte data) { // Wait Handshake low; Generate clock and serialize data from DSLR byte mask; delayMicroseconds(15); for (mask = 0x01; mask>0; mask <<= 1) { digitalWrite(DSLR_CLK, LOW); if (data & mask){ // choose bit digitalWrite(DSLR_DATA,HIGH); // send 1 } else{ digitalWrite(DSLR_DATA,LOW); // send 0 } delayMicroseconds(16); digitalWrite(DSLR_CLK, HIGH); delayMicroseconds(16); } } /* ************************************************************************************************************************************ * Main loop * process event: * - DSLR input according i-TTL state * - Test Button * - Test requested * - Time Out (long time out) * * Short time out on HandShake is a detection of aborted frame according protocol. ************************************************************************************************************************************ */ void loop() { // i-TTL Frame state decoder ------------------------------------ // DISABLE // DSLR OFF, STANDBY or SCA not connected. // WAIT // DSLR ON start nego begin frame // STANDBY // DSLR standby (protocole standby - already negotiated/sync) // READY // 1st pulse Handshake received - interface synchronized, read cde and decode // RECEIVED // Frame received, process frame - During process, manage i-TTL Prococol state switch(ITTL_FrameState) { // *********************************** Process DSLR input according i-TTL protocol state **************** case DISABLE: if (digitalRead(DSLR_Hshake) == HIGH) { // test cas flash ON; boitier off et s'active. ArmTimeOut(); #ifdef DEBUG_ITTL1 Serial.println("detect Hanshake HIGH"); #endif delayMicroseconds(1300); digitalWrite(DSLR_CLK, HIGH); ITTL_FrameState = WAIT; } break; case WAIT: if (digitalRead(DSLR_DATA) == LOW) { // Body is on - send recurrent DATA pulse, will sync on next pulse ArmTimeOut(); #ifdef DEBUG_ITTL1 Serial.println("detect 1 of recurrent data pulse "); #endif pinMode(DSLR_DATA,OUTPUT); digitalWrite(DSLR_DATA,LOW); while (digitalRead(DSLR_Hshake)==HIGH && TimeOut==0 ) { } // attend Handshake // release data pinMode(DSLR_DATA,INPUT_PULLUP); if (TimeOut==0){ ITTL_FrameState = READY; } } break; case STANDBY: if (digitalRead(DSLR_DATA) == LOW) { ITTL_FrameState = WAIT; } break; case READY: // receive 1st Byte of a Frame -- Ready to decode Cde and read or send remaining part of the frame ++++ if (digitalRead(DSLR_Hshake)==LOW ) { ArmTimeOut(); delayMicroseconds(15); // initialement 15 Cde=DSLR_ReadByte(); while (digitalRead(DSLR_Hshake) == LOW && TimeOut==0) { } // attend fin Handshake #ifdef DEBUG_ITTL1 Serial.println(); Serial.print("cde=");Serial.print(Cde,HEX);Serial.print(","); #endif // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++decode first byte to identify cde ++++++++++++++ Data_Direction = IN; // default value; overwriten when needed switch (Cde) { case 0xA1: n=A1_LEN; Data_Direction = OUT; break; case 0xB1: n=10; break; case 0xA2: n=A2_LEN; Data_Direction = OUT; break; case 0xB0: n=15; break; case 0xA0: n=A0_LEN; Data_Direction = OUT; break; case 0xD7: // pre flash n=0; digitalWrite(TP1,LOW); break; case 0xD8: n=1; break; case 0xD3: // power cde n=3; digitalWrite(TP2,LOW); break; case 0xD5: // Modeling light start (stop after 1sec.) n=0; break; case 0xD0: // AF assist 01 (F0) on 00 (00) off n=2; break; case 0xD1: // pulse anti-yeux rouge 1 pulse 1/64 toutes les 0,25ms jusqu,à cde stop. n=1; break; case 0xC0: // main flash strobe confirmation ( byte signification unkown) n=5; break; case 0xE0: // standby n=2; #ifdef DEBUG_ITTL Serial.println(" E0..."); //XXXX #endif break; default: n=0; #ifdef DEBUG_ITTL Serial.println(" Other..."); //XXXX #endif break; } if (Data_Direction == OUT) { // ++++++++++++++++++++++++++++++++++++++++ Send byte Capability or Info +++++++++++++ // send answer to DSLR p=0; Crc=1; DSLR_OpenDataOutput(); while (n !=0) { // loop to write the answer of the cde. ArmTimeOut_1(); while (digitalRead(DSLR_Hshake) == HIGH && TimeOut1 == 1) { } // attend Handshake if(TimeOut1 > 1 ) {break;} Timer1.stop(); delayMicroseconds(20); // initalement 26 20 à 40 fonctionne avec D7000 if (Cde==0xA0) { b = MessageA0[p]; if (p==0) { // send flash status and ack b=0x00; if (Ack_requested==0) { b=b | BIT_NIK_NOACK;} // Ack: bit = 0 if no ACK Bit=1 if (digitalRead(FLASH_READY) == LOW ) {b=b | BIT_NIK_READY;} } if (p==1) {b=Flash_NikMode;} //send selected mode if (p==14) { if (digitalRead(FLASH_READY) == LOW ) { b=FlashActivityLevel; } else { b=0xFF; } } // Power capacity 00 full - >0 lower - FF recycling } else if (Cde==0xA1) { b = MessageA1[p]; } else if (Cde==0xA2) { b = MessageA2[p]; } if (n==1) { // recalculate CRC //Serial.print("CRC=");Serial.print(Crc,HEX);Serial.print(" b=");Serial.println(b,HEX); b=Crc; // will send calculated Crc } else { Crc = Crc + b; } DSLR_WriteByte(b); n--; p++; #ifdef DEBUG_ITTL1 Serial.print(",");Serial.print(b,HEX); #endif while (digitalRead(DSLR_Hshake) == LOW && TimeOut==0) { } // attend fin Handshake if(TimeOut==1 ) {break;} } Timer1.stop(); DSLR_CloseDataOutput(); #ifdef DEBUG_ITTL2 if (TimeOut== 1){ Serial.println("data send time-out"); } if (TimeOut1 > 1){ Serial.println("data send aborted"); } #endif } else { //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Read byte to complete cde ++++++++++++++ while (n !=0) { // loop to read the data byte of the cde. n--; ArmTimeOut_1(); while (digitalRead(DSLR_Hshake) == HIGH && TimeOut1==1) { } // attend Handshake if(TimeOut1 > 1 ) {break;} Timer1.stop(); delayMicroseconds(15); // initialement 26, 15 OK avec D7000; if (Cde==0xD3 && n==0) { d=0xD3; DSLR_OpenDataOutput(); DSLR_WriteByte(d); // send ack to DSLR DSLR_CloseDataOutput(); } else { d = DSLR_ReadByte(); } #ifdef DEBUG_ITTL1 Serial.print(d,HEX);Serial.print(","); #endif if (Cde==0xD3) { if(n==1) { Flash_Power_Index=d; } // if(n==2) {} // lecture Flash context } if (Cde==0xB0) { if(n==7) { Exposure_Correction = d; } if(n==13) {d=d&4; if(d==0){ Ack_requested=1; } else { Ack_requested=0; }} } while (digitalRead(DSLR_Hshake) == LOW && TimeOut==0) { } // attend fin Handshake if(TimeOut==1 ) {break;} } Timer1.stop(); #ifdef DEBUG_ITTL2 if (TimeOut== 1){ Serial.println("data read time-out"); } if (TimeOut1 > 1){ Serial.println("data read aborted"); } #endif } if ( TimeOut==1 || TimeOut1 > 1 ) { if (TimeOut1 > 1){ digitalWrite(TP3,LOW);} ITTL_FrameState = WAIT; #ifdef DEBUG_ITTL2 Serial.println();Serial.print(" Time Out WAIT frame T3 T1 ");Serial.print(TimeOut);Serial.print(" ");Serial.print(TimeOut1); #endif } else { ITTL_FrameState = RECEIVED; } } digitalWrite(TP1,HIGH); digitalWrite(TP2,HIGH); digitalWrite(TP3,HIGH); break; case RECEIVED : // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Execute cde ++++++++++++++++++++++++++++ ITTL_FrameState = WAIT; switch (Cde) { case 0xD7: #ifdef DEBUG_ITTL Serial.println();Serial.print("pre-flash"); #endif delayMicroseconds(40); DSLR_OpenDataOutput(); delayMicroseconds(408); // + 4µs de traitement DoPreFlash(); delayMicroseconds(5800); // + 4µS traitement + Preflash duration 6,1ms after flash start. DSLR_CloseDataOutput(); break; case 0xD8: #ifdef DEBUG_ITTL Serial.print(" pre-flash 30%"); #endif DoPreFlash30(); break; case 0xD3: DSLR_OpenDataOutput(); if (Exposure_Correction >0x80) {temp = (~(Exposure_Correction-1))<<1; } else {temp = (~(Exposure_Correction<<1))+1; } temp=temp+Flash_Power_Index; if (temp < 0x54) { // min power Flash_Duration = Flash_Duration_Long[0]; } else if (temp > 0xA8) { Flash_Duration = Flash_Duration_Long[84]; // max power } else { Flash_Duration = Flash_Duration_Long[temp+(FLASH_ADJUST-0x54)]; // + inital Lab adjustment minus offset of the Nikon power cde code } #ifdef DEBUG_ITTL Serial.print(" Power level:");Serial.print(Flash_Power_Index,HEX);Serial.print(" Duration:");Serial.print(Flash_Duration);Serial.print(" Expo Comp:");Serial.print(Exposure_Correction);Serial.print(" Index:");Serial.print(temp,HEX); #endif delayMicroseconds(612); // + 6µS traitement 618µS d'activation. DSLR_CloseDataOutput(); break; case 0xD5: Serial.print(" D5...."); DoPilot(); break; case 0xA0: if (ITTL_State == DISABLE) { ITTL_State = STARTED; } // reprise dialog sur time out flash mais pas coté boitier. if (ITTL_State == STARTED) { ITTL_State = ACTIV; #ifdef DEBUG_ITTL Serial.print("ITTL ACTIV"); #endif } break; case 0xA1: ITTL_State = INIT; #ifdef DEBUG_ITTL Serial.println("ITTL INIT"); #endif break; case 0xA2: ITTL_State = STARTED; #ifdef DEBUG_ITTL Serial.println("ITTL STARTED"); #endif break; case 0xD0: #ifdef DEBUG_ITTL Serial.println("ITTL AF Assist cde"); #endif AF_Assist=2; digitalWrite(AF_ASSIST, LOW); break; case 0xB0: if (AF_Assist > 0) { AF_Assist--; if (AF_Assist == 0) { digitalWrite(AF_ASSIST, HIGH); } } break; case 0xE0: Timer3.stop(); ITTL_FrameState = STANDBY; break; } break; } if (TimeOut == 1) { #ifdef DEBUG_ITTL Serial.println(); Serial.println("ITTL - Time Out"); #endif ArmTimeOut(); Timer3.stop(); ITTL_FrameState = DISABLE; ITTL_State = INACTIV; pinMode(DSLR_DATA, INPUT_PULLUP); digitalWrite(DSLR_CLK, LOW); delay(10); } if (digitalRead(DSLR_SYNC) == LOW) { //DSLR Sync X activ ----------------------------------------- switch (ITTL_State) { case ACTIV: pinMode(DSLR_SYNC,OUTPUT); digitalWrite(DSLR_SYNC,LOW); if (Flash_Mode == TTL) { DoFlash(); #ifdef DEBUG_ITTL Serial.println("X TTL main flash done"); #endif } else { StartFlash(); #ifdef DEBUG_ITTL Serial.println("X A ou M main flash done"); #endif } delayMicroseconds(2800); pinMode(DSLR_SYNC,INPUT_PULLUP); while (digitalRead(DSLR_DATA)==HIGH && TimeOut==0) { } // skip 1st Data low pulse following main flash. while (digitalRead(DSLR_DATA)==LOW) { } break; default: pinMode(DSLR_SYNC,OUTPUT); digitalWrite(DSLR_SYNC,LOW); if (Flash_Mode == TTL) { #ifdef DEBUG_ITTL Serial.println("X TTL - NO flash possible"); #endif } else { StartFlash(); #ifdef DEBUG_ITTL Serial.println("X A ou M - ITTL NOT ACTIV"); #endif } delayMicroseconds(2800); pinMode(DSLR_SYNC,INPUT_PULLUP); while (digitalRead(DSLR_SYNC)==LOW) { } break; } } if (Flash_TestRequest == 1 ) { // Process Flash Test event ----------------------------------------- if (Flash_TestBlocked == 0) { // remise à 0 gérée dans boucle timer du controle led DoFlashTest(); Flash_TestBlocked = TEST_BLOCK_DURATION; } } if (digitalRead(TEST_BUTTON) == LOW ) { // Process Button Test event- ---------------------------------- Flash_TestRequest = 1; } if ( ITTL_FrameState == DISABLE ) { // Control LED depending of the protocol activation --------------- // cde LED - Flash blink 1 sec T1--; if (T1 == 0) { ReleaseTestButton(); ReadMode(); T1= 20000; T2--; if (T2==1) { digitalWrite(LED_SCA, LOW); #ifdef DEBUG_FLASH Serial.print("Flash Mode = ");Serial.println(Flash_Mode); #endif } if (T2==0) { digitalWrite(LED_SCA, HIGH); T2=11; } } } else { // protocol i-TTL actif // cde LED - Flash blink 1 sec T1--; if (T1 == 0) { ReleaseTestButton(); ReadMode(); T1= 30400; T2--; if (T2==5) { digitalWrite(LED_SCA, LOW); #ifdef DEBUG_FLASH Serial.print("Flash Mode=");Serial.print(Flash_Mode);Serial.print(" Nikon Mode=");Serial.println(Flash_NikMode); #endif } if (T2==0) { digitalWrite(LED_SCA, HIGH); T2=10; } } } } // ***************** end main loop ************************************************************************************************************ void ReleaseTestButton() { if (Flash_TestBlocked > 0) { Flash_TestBlocked--; if (Flash_TestBlocked == 0) { Flash_TestRequest = 0; } } } void ReadMode() { Analog_Mode = analogRead(FLASH_MODE_IN); // not used as blocking until conversion finished if (Analog_Mode > Seuil_TTL) { if (Analog_Mode < Seuil_A) { Flash_Mode = TTL; if (digitalRead(SW1) == HIGH) { Flash_NikMode = NIK_TTLBL; } else { Flash_NikMode = NIK_TTL; } } else if (Analog_Mode < Seuil_M) { Flash_Mode = A; Flash_NikMode = NIK_A; } else { Flash_Mode = M ; Flash_NikMode = NIK_M; } } else { Flash_Mode = UNDEFINED; Flash_NikMode = UNDEFINED; } #ifdef DEBUG_FLASH_MODE Serial.print("Flash Mode =");Serial.print(Analog_Mode);Serial.print(" LSB");Serial.print(" Mode="),Serial.println(Flash_Mode); #endif } void DoPilot() { for (byte z=0 ; z<=9; z++) { DoFlash2(40); delay(120); Serial.print("."); } } void DoFlashTest() { // If TTL programm control the strobe duration, otherwise strobe duration manage by flashgun if (Flash_Mode == TTL) { #ifdef DEBUG_FLASH Serial.println("Flash Test TTL (1/64)"); #endif DoFlash2(TEST_FLASH_DURATION); // duration µS } if (Flash_Mode == A || Flash_Mode == M) { #ifdef DEBUG_FLASH Serial.println("Flash Test"); #endif StartFlash(); } } void DoPreFlash() { // Do pre flash if (Flash_Mode==TTL) { digitalWrite(DSLR_CLK, LOW); DoFlash2(PRE_FLASH_DURATION); delayMicroseconds(94); // Increase to emulate optic detection 28 µS + 76 µS digitalWrite(DSLR_CLK, HIGH); } else { digitalWrite(DSLR_CLK, LOW); delayMicroseconds(146); digitalWrite(DSLR_CLK, HIGH); } } void DoPreFlash30() { // Do pre flash 30% digitalWrite(DSLR_CLK, LOW); DoFlash2(PRE_FLASH30_DURATION); delayMicroseconds(94); // Increase to emulate optic detection digitalWrite(DSLR_CLK, HIGH); } void DoFlash() { // using Flash power received from DSLR. - TTL only StartFlash2(); delayMicroseconds(Flash_Duration); StopFlash(); } void DoFlash2 (int T) { // same as DoFlash but T Flash duration µS as parameter T = (T-2); //remove duration code execution before delay StartFlash2(); delayMicroseconds(T); // replace by duration, minus 20µS (duration of start pulse) StopFlash(); } void StartFlash() { // to call in case A or M mode... digitalWrite(FLASH_Sync, LOW); delayMicroseconds(2); // initialement 10, 1 ratés en A; pas de départ en M; 2 OK digitalWrite(FLASH_Sync, HIGH); } void StartFlash2() { digitalWrite(FLASH_Sync, LOW); } void StopFlash() { digitalWrite(FLASH_Sync, HIGH); digitalWrite(FLASH_Stop, HIGH); delayMicroseconds(2); // initialement 30, digitalWrite(FLASH_Stop, LOW); }