Toyota GR86, 86, FR-S and Subaru BRZ Forum & Owners Community - FT86CLUB

Toyota GR86, 86, FR-S and Subaru BRZ Forum & Owners Community - FT86CLUB (https://www.ft86club.com/forums/index.php)
-   Software Tuning (https://www.ft86club.com/forums/forumdisplay.php?f=88)
-   -   Open Source Flex Fuel (https://www.ft86club.com/forums/showthread.php?t=94751)

elBarto 12-12-2015 07:14 PM

Very nice work ztan. I don't understand anything about the coding but I love your dedication with this car.

send using the coffeemaker

thambu19 12-13-2015 09:59 AM

You are a pro!

Sent from my HTC One_M8 using Tapatalk

steve99 12-13-2015 02:00 PM

@ztan

would it be possible to use the "Cranking Fuel IPW Compensation (IAT) " table instead

looks like the temps could be rescaled its currently not used all 0% compensation

shiv used it in the F10G E85 roms in 2.07 tunes as the cranking IPW tables were not defined correctly so could not be changed.

ztan 12-13-2015 06:59 PM

Cranking Compensation v.2
 
*** Cranking code updated - my inferences from my logs to make v.2 code were wrong due to the delay in the Arduino Ethanol sensor controller starting to read a value ***

I tried to apply cranking compensation for E% applied to E0 fuelling and it didn't work - I think there was something in the code which does not allow positive compensation. To use compensations < 1.0, I have scaled cranking fuel to E85 and down-compensated for smaller E%. This one seems to work.

I've multiplied E0 cranking tables by the following to get E85 cranking:
Code:

ECT
-40  -30  -20  -10  0    10    20    30    40    50    60    70    80    90    100  110
1.54  1.54  1.54  1.54  1.51  1.46  1.36  1.26  1.17  1.10  1.04  1.01  1.00  1.00  1.00  1.00

I've left the modified the code from post #32 which uses the IAT compensation part of the routine and changed the segment starting at 0xB9870:

Code:

000B9870            FlexFuel_Cranking_Comp:                ; CODE XREF: Cranking_Compensations
000B9870                                                    ; Cranking_Compensations_0
000B9870                                                    ; DATA XREF: ...
000B9870 4F 22                      sts.l  pr, @-r15      ; Store System Register Long
000B9872 F4 48                      fmov.s  @r4, fr4        ; r4=ECT
000B9874 D2 14                      mov.l  #Pull_2D_A, r2  ; Move Immediate Long Data
000B9876 D4 1A                      mov.l  #Ethanol_Cranking_Comp_Table, r4 ; Move Immediate Long Data
000B9878 42 4B                      jsr/n  @R2 ; Pull_2D_A ; Jump to Subroutine with No delay slot
000B987A C7 17                      mova    FF_Mult_Max, r0 ; 1.35
000B987C D4 0E                      mov.l  #RAM_FF_Crank_Comp, r4 ; Move Immediate Long Data
000B987E F5 08                      fmov.s  @r0, fr5        ; Floating-point move single precision
000B9880 D6 0A                      mov.l  #RAM_Flex_Fuelling_Multiplier, r6 ; Move Immediate Long Data
000B9882 F4 68                      fmov.s  @r6, fr4        ; Floating-point move single precision
000B9884 F4 51                      fsub    fr5, fr4        ; fr4-FF_Mult_Max
000B9886 F5 9D                      fldi1  fr5            ; Floating-point load immediate 1.0
000B9888 F5 4E                      fmac    fr0, fr4, fr5  ; 1+(crank_comp*(FF_Mult - FF_Mult_Max))
000B988A F0 5C                      fmov    fr5, fr0        ; Floating-point move
000B988C F4 0A                      fmov.s  fr0, @r4        ; Floating-point move single precision
000B988E 4F 26                      lds.l  @r15+, pr      ; Load to System Register Long
000B9890 00 6B                      rts/n                  ; Return from Subroutine with No delay slot

000B98AC FF F8 D4 14 off_B98AC:      .data.l RAM_Flex_Fuelling_Multiplier
000B98AC                                                    ; DATA XREF: sub_B97C0
000B98B8 FF F8 D4 20 off_B98B8:      .data.l RAM_FF_Crank_Comp ; DATA XREF: sub_B97C0
000B98C8 00 01 13 88 off_B98C8:      .data.l Pull_2D_A      ; DATA XREF: sub_B97C0
000B98D8 3F AC CC CD FF_Mult_Max:    .float 1.35            ; DATA XREF: sub_B97C0

Interestingly, the Crank tables are defined as "Injector pulse width" but look like they get inserted into the code as high up as the MAF_V value, but don't affect the engine load value that I log.

Seems to work. Cranking with Flex sender plugged and unplugged:

Code:

MAF_V  MAP      ECT      Port_IPW    Direct_IPW  Throttle  MAF      Load      Accel  Ethanol    FF_Mult  FF_Cranking
1.07422 99.7076  47.8367  9.46926      0          6.07415  1.63601  0.452178  0      0.0976563  1.00038  0.900488
1.2207  98.2765  48.2156  9.75813      0          5.73641  2.44261  0.451798  0      59.9854    1.24994  0.972127




myioz86 12-14-2015 12:09 AM

Have no idea about all this teck stuff but thanks for all the great work you have done for this E85 OFT project Ztan.
We all appreciate it .

ztan 12-18-2015 06:34 PM

Updated Arduino Flex sender code
 
There is a delay of around 1500 ms before the Arduino initializes and begins to run the frequency.measure code. There is a small delay in getting an ethanol value out to the ECU whilst the arduino is waiting for a number of frequency.measure periods to pass (at 100Hz, 100 cycles take 1 sec or 1000ms).

To minimise this, I've written an average voltage sender value to EEPROM which is restored as soon as the Arduino boots and then gets updated with a moving average value every time the frequency.measure value gets updated.

Code (I've commented off PLX code which I am happy just logging now):
Code:

//Flex Fuel sensor code
//Input frequency on pin 8 - pulled up to 5V through 1.8K resistor
//V_out pin 3 - 0-5V output through 1.8K resistor with 10uf capacitor to ground
//PLX iMFD serial packet on Tx pin 0 through 3.3V TTL voltage divider (3.3K/6.8K)

//TRAC double click code
//Input switch on pin 6 - pulled up to 5V through 3.3K resistor
//Output on pin 10 through NPN transistor to take VSC connection to ground

#include <Arduino.h>
#include <FreqMeasure.h>
#include <EEPROM.h>

//FlexFuel sensor
double sum = 0;
int count = 0;
int EE_V_add = 0;
int ethanol_int, V_out_int;
float freq, ethanol, V_out, V_out_avg, E_scalar;
float V_out_default = 147;
float E0 = 55.4; //calibration data for pure gasoline
float E85 = 130.8; //calibration data for E85

//PLX data
//long P0, P1, Pdelta;
//byte PLXpacket[7] {0x80, 0x00, 0x11, 0x00, 0x00, 0x00, 0x40};

//PLX iMFD packet, sent every 100ms:
//0x80      Start byte
//0x00 0x11 Sensor device fuel level
//0x00      Sensor instance
//0x00 0x00 Sensor value (integer, unscaled)
//0x40      Stop byte

//TRAC switch double click
bool TRAC_buttonMonitor = HIGH;
int debounce = 20;
int doubleClick = 200;
int longClick = 3500;
int TRAC_initializeDelay = 4000;
int TRAC_buttonState = 4; //initialize to 0 for normal operation, 4 for on by default after delay
long TRAC_buttonCounter = 0;


void setup()
{
  pinMode (3, OUTPUT);
  pinMode (10, OUTPUT);
  digitalWrite (10, LOW);
  pinMode (6, INPUT);

  EEPROM.get(EE_V_add, V_out_avg); //load last V_out_avg
  if (isnan(V_out_avg))
  {
    V_out_avg = V_out_default;
  }
  V_out_int = (int)V_out_avg; //convert to integer for analogWrite
  analogWrite(3, V_out_int); //output V_out as PWM voltage on pin 3

  FreqMeasure.begin();
  //  Serial.begin(19200);
  //  P0 = millis();
  E_scalar = (E85 - E0) / 85;
}

void loop()
{

  //Read FlexFuel sensor frequency
  if (FreqMeasure.available())
  {
    // average several readings together
    sum = sum + FreqMeasure.read();
    count = count + 1;
    if (count > 100)
    {
      freq = FreqMeasure.countToFrequency(sum / count);
      sum = 0;
      count = 0;

      //Convert frequency to E%

      ethanol = (freq - E0) / E_scalar; //scale frequency to E% interpolating E0 and E85 values
      if (ethanol > 100)
      {
        ethanol = 100;
      }
      if (ethanol < 0)
      {
        ethanol = 0;
      }
      ethanol_int = (int)ethanol;

      //FlexFuel voltage output

      V_out = 255 - (2.55 * ethanol);
      V_out_avg = V_out_avg + (0.05 * (V_out - V_out_avg)); //V_out_avg as moving average
      EEPROM.put( EE_V_add,  V_out_avg ); //store V_out_avg to EEPROM

      V_out_int = (int)V_out_avg; //convert to integer for analogWrite
      analogWrite(3, V_out_int); //output V_out_avg as PWM voltage on pin 3
    }
  }
  //PLX data packet

  //P1 = millis(); //send PLX packet on Tx pin every 100ms
  //Pdelta = P1 - P0;
  //if (Pdelta >= 100)
  //{
  //  P0 = P1;
  //  PLXpacket[5] = ethanol_int; //set data byte in PLX packet to E%
  //  Serial.write(PLXpacket, 7);
  //}

  //TRAC switch doubleclick

  TRAC_buttonMonitor = digitalRead(6);
  switch (TRAC_buttonState)
  {
    case 0: //inactive

      if (TRAC_buttonMonitor == LOW)  // button pressed
      {
        digitalWrite (10, HIGH); //Transistor on
        TRAC_buttonState = 1; //increment state
      }
      break;

    case 1: //check for release
      if (TRAC_buttonMonitor == HIGH) //if button released
      {
        TRAC_buttonCounter = millis(); //start counter
        TRAC_buttonState = 2; //increment state
      }
      break;

    case 2: //wait for doubleClick
      if (TRAC_buttonMonitor == LOW && (millis() - TRAC_buttonCounter) > debounce && (millis() - TRAC_buttonCounter) < doubleClick) //second click registered
      {
        TRAC_buttonState = 3; //increment state
      }
      else if ((millis() - TRAC_buttonCounter) > doubleClick)
      {
        digitalWrite (10, LOW); //Transistor off
        TRAC_buttonState = 0; //reset state
      }
      break;

    case 3: //doubleClick made
      if ((millis() - TRAC_buttonCounter) > longClick)
      {
        digitalWrite (10, LOW); //Transistor off
        TRAC_buttonState = 0; //reset state
      }
      break;

    case 4: //initialize after delay by default
      if (millis() > TRAC_initializeDelay)
      {
        digitalWrite (10, HIGH); //Transistor on
        TRAC_buttonCounter = millis(); //start counter
        TRAC_buttonState = 3; //set state to doubleClick
      }
      break;
  }

}


ztan 12-18-2015 06:46 PM

Cranking Compensation v.3
 
1 Attachment(s)
The delay in the Arduino sensor had me cranking with ethanol in the tank with the unit sending E0 for a short while (usually whilst cranking). This made me think that the IAT compensation was unable to generate a positive compensation. I found the error in the logs and have modified the Arduino code to boot with a value restored.

I have changed the cranking compensation code v.1 to work off E0 cranking tables and apply correction that are close to Wayno's cranking values (FF_Multiplier is squared so that at E85, at E85 FF_Multiplier of 1.4 becomes a FF_Cranking of 2). This code works well with the changes to the Arduino code.

Cranking with Arduino Flex unplugged (E0)
Cranking with Arduino Flex plugged (E75 in tank)

Code:

000B9870            FlexFuel_Cranking_Comp:                ; CODE XREF: Cranking_Compensations
000B9870                                                    ; Cranking_Compensations_0
000B9870                                                    ; DATA XREF: ...
000B9870 4F 22                      sts.l  pr, @-r15      ; Store System Register Long
000B9872 F4 48                      fmov.s  @r4, fr4        ; r4=ECT
000B9874 D2 18                      mov.l  #Pull_2D_A, r2  ; Move Immediate Long Data
000B9876 D4 1A                      mov.l  #Ethanol_Cranking_Comp_Table, r4 ;Move Immediate Long Data
000B9878 42 4B                      jsr/n  @R2 ;  Jump to Subroutine with No delay slot
000B987A D4 0F                      mov.l  #RAM_FF_Crank_Comp, r4 ; Pull_2D_A ; Move Immediate Long Data
000B987C F5 9D                      fldi1  fr5            ; Floating-point load immediate 1.0
000B987E D6 0B                      mov.l  #RAM_Flex_Fuelling_Multiplier, r6 ; Move Immediate Long Data
000B9880 F4 68                      fmov.s  @r6, fr4        ; Floating-point move single precision
000B9882 F4 42                      fmul    fr4, fr4        ; FF_Mult^2
000B9884 F4 51                      fsub    fr5, fr4        ; FF_Mult^2-1
000B9886 F5 4E                      fmac    fr0, fr4, fr5  ; 1+(Crank_Comp*(FF_Mult^2-1))
000B9888 F0 5C                      fmov    fr5, fr0        ; 1+(crank_comp * (FF_Mult - FF_Mult_Max))
000B988A F4 0A                      fmov.s  fr0, @r4        ; Floating-point move single precision
000B988C 4F 26                      lds.l  @r15+, pr      ; Load to System Register Long
000B988E 00 6B                      rts/n                  ; Return from Subroutine with No delay slot
000B9890            ; ---------------------------------------------------------------------------


000B98D8 00 01 13 88 off_B98D8:      .data.l Pull_2D_A      ; DATA XREF: sub_B97C0


ztan 12-18-2015 06:54 PM

Fuel Consumption Display
 
This code simply multiplies the value that is returned from the Display multiplier table by the FlexFuel Multiplier (E0=0, E85=1.4).

Stock code A01G:
Code:

ROM:0003F6D2 FF 9E                      fmac    fr0, fr9, fr15
ROM:0003F6D4 D4 4A                      mov.l  #Table_Fuel_Multiplier_Display_Offset, r4
ROM:0003F6D6 D2 3B                      mov.l  #Pull_2D_A, r2
ROM:0003F6D8 42 0B                      jsr    @R2 ; Pull_2D_A
ROM:0003F6DA F4 FC                      fmov    fr15, fr4
ROM:0003F6DC 02 80 88 F8                movi20  #RAM_Fuel_Multiplier_Display_Offset, r2
ROM:0003F6E0 32 F1 30 01                fmov.s  fr15, @(4,r2)
ROM:0003F6E4 F0 F2                      fmul    fr15, fr0

ROM:0003F800 00 0B 20 24 off_3F800:      .data.l Table_Fuel_Multiplier_Display_Offset
ROM:0003F800                                                    ; DATA XREF: sub_3F674

Flex Fuel Code:
Code:

0003F6D2 FF 9E                      fmac    fr0, fr9, fr15  ; PI volume + GDI volume
0003F6D4 D2 4A                      mov.l  #FlexFuel_Display, r2
0003F6D6 42 0B                      jsr    @R2 ; FlexFuel_Display
0003F6D8 F4 FC                      fmov    fr15, fr4
0003F6DA F0 42                      fmul    fr4, fr0
0003F6DC 02 80 88 F8                movi20  #RAM_Fuel_Multiplier_Display, r2
0003F6E0 32 F1 30 01                fmov.s  fr15, @((RAM_Fuel_Volume_Display - RAM_Fuel_Multiplier_Display),r2)
0003F6E4 F0 F2                      fmul    fr15, fr0

0003F800 00 0B 98 90 off_3F800:      .data.l FlexFuel_Display ; DATA XREF: sub_3F674

000B9890            FlexFuel_Display:                      ; CODE XREF: sub_3F674
000B9890                                                    ; DATA XREF: sub_3F674
000B9890 4F 22                      sts.l  pr, @-r15
000B9892 02 10 13 88                movi20  #Pull_2D_A, r2
000B9896 D4 17                      mov.l  #Table_Fuel_Multiplier_Display_Offset, r4
000B9898 42 4B                      jsr/n  @R2 ; Pull_2D_A
000B989A D4 04                      mov.l  #RAM_Flex_Fuelling_Multiplier, r4
000B989C F4 48                      fmov.s  @r4, fr4
000B989E 4F 26                      lds.l  @r15+, pr
000B98A0 00 6B                      rts/n

000B98AC FF F8 D4 14 off_B98AC:      .data.l RAM_Flex_Fuelling_Multiplier
000B98AC                                                    ; DATA XREF: sub_B97C0

000B98F4 00 0B 20 24 off_B98F4:      .data.l Table_Fuel_Multiplier_Display_Offset
000B98F4                                                    ; DATA XREF: sub_B97C0


ztan 02-20-2016 06:16 AM

Updated Arduino Circuit and Flex sender code
 
1 Attachment(s)
A couple of issues sorted out:

1. PLX display died and I didn't figure out for a while until I read the iMFD serial chain notes again carefully - the two data bytes only use the first 6 bits of each and the last 2 need to be "00". Arduino code has been updated to send data in this format and the display works properly.

2. Occasionally, the traction control would switch back on again, usually under hard acceleration. I suspect due to noise on the circuit; went back and made the power supply more robust (caps not shown on circuit below), added filtering to the NPN transistor, and reduced the B-E current to reduce the chance of false noise switching it on. Now traction control stays off at all times.

3. Increased filtering capacitance on the output line to the ECU to reduce sender noise.

4. Ethanol moving average gets stored in EEPROM every 5 minutes rather than every cycle and is the first thing to get sent out when booting the arduino in order to reduce the time a flex signal is available to the ECU.

Code:

//Flex Fuel sensor code
//Input frequency on pin 8 - pulled up to 5V through 1.8K resistor
//V_out pin 3 - 0-5V output through 1.8K resistor with 100uF capacitor to ground
//PLX iMFD serial packet on Tx pin 0 through 3.3V TTL voltage divider (3.3K/6.8K)

//TRAC double click code
//Input switch on pin 6 - pulled up to 5V through 3.3K resistor + 3.3uF capacitor.
//Output on pin 10 through NPN transistor to take VSC connection to ground

#include <Arduino.h>
#include <FreqMeasure.h>
#include <EEPROM.h>

//FlexFuel sensor
double sum = 0;
int count = 0;
int ethanol_int, V_out_int;
float freq, ethanol, V_out, V_out_avg, E_scalar;
float E0 = 55.4; //calibration data for pure gasoline
float E85 = 130.8; //calibration data for E85

//EEPROM store
int EE_V_addr = 0;
float V_out_default = 147;
long Elast, Enow, Edelta;

//PLX data
long Plast, Pnow, Pdelta;
byte PLXpacket[7] {0x80, 0x00, 0x11, 0x00, 0x00, 0x00, 0x40};

//PLX iMFD packet, sent every 100ms:
//0x80      Start byte
//0x00 0x11 Sensor device fuel level
//0x00      Sensor instance
//0x00 0x00 Sensor value (integer, unscaled)
//0x40      Stop byte

//TRAC switch double click
bool TRAC_buttonMonitor = HIGH;
int debounce = 20;
int doubleClick = 200;
int longClick = 3000;
int TRAC_initializeDelay = 5000;
int TRAC_buttonState = 4; //initialize to 0 for normal operation, 4 for on by default after delay
long TRAC_buttonCounter = 0;


void setup()
{
  pinMode (3, OUTPUT);
  pinMode (10, OUTPUT);
  digitalWrite (10, LOW);
  pinMode (6, INPUT);

  EEPROM.get(EE_V_addr, V_out_avg); //load last V_out_avg
  if (isnan(V_out_avg))
  {
    V_out_avg = V_out_default;
  }
  V_out_int = (int)V_out_avg; //convert to integer for analogWrite
  analogWrite(3, V_out_int); //output V_out as PWM voltage on pin 3

  Elast = millis();

  E_scalar = (E85 - E0) / 85;

  FreqMeasure.begin();
  Serial.begin(19200);
  Plast = millis();
  Serial.write(PLXpacket, 7);
}

void loop()
{

  //Read FlexFuel sensor frequency
  if (FreqMeasure.available())
  {
    // average several readings together
    sum = sum + FreqMeasure.read();
    count = count + 1;
    if (count > 24)
    {
      freq = FreqMeasure.countToFrequency(sum / count);
      sum = 0;
      count = 0;

      //Convert frequency to E%

      ethanol = (freq - E0) / E_scalar; //scale frequency to E% interpolating E0 and E85 values
      if (ethanol > 100)
      {
        ethanol = 100;
      }
      if (ethanol < 0)
      {
        ethanol = 0;
      }
      ethanol_int = (int)ethanol;

      //FlexFuel voltage output

      V_out = 255 - (2.55 * ethanol);
      V_out_avg = V_out_avg + (0.1 * (V_out - V_out_avg)); //V_out_avg as moving average
      V_out_int = (int)V_out_avg; //convert to integer for analogWrite

      analogWrite(3, V_out_int); //output V_out as PWM voltage on pin 3
    }
  }

  //Store EEPROM data every 5 minutes

  Enow = millis();
  Edelta = Enow - Elast;
  if (Edelta >= 300000)
  {
    Elast = Enow;
    EEPROM.put(EE_V_addr,  V_out_avg ); //store V_out_avg to EEPROM
  }

  //PLX data packet

  Pnow = millis(); //send PLX packet on Tx pin every 100ms
  Pdelta = Pnow - Plast;
  if (Pdelta >= 100)
  {
    if (ethanol_int > 63) { //PLX iMFD only uses 6 LSB bits, 2 MSB must be 00 in each byte
      Plast = Pnow;
      PLXpacket[4] = 0x01;
      int ethanol_int_LSB = ethanol_int - 64;
      PLXpacket[5] = ethanol_int_LSB;
      Serial.write(PLXpacket, 7);
    }
    else {
      Plast = Pnow;
      PLXpacket[4] = 0x00;
      PLXpacket[5] = ethanol_int; //set data byte in PLX packet to E%
      Serial.write(PLXpacket, 7);
    }
  }

  //TRAC switch doubleclick

  TRAC_buttonMonitor = digitalRead(6);
  switch (TRAC_buttonState)
  {
    case 0: //inactive

      if (TRAC_buttonMonitor == LOW)  // button pressed
      {
        digitalWrite (10, HIGH); //Transistor on
        TRAC_buttonState = 1; //increment state
      }
      break;

    case 1: //check for release
      if (TRAC_buttonMonitor == HIGH) //if button released
      {
        TRAC_buttonCounter = millis(); //start counter
        TRAC_buttonState = 2; //increment state
      }
      break;

    case 2: //wait for doubleClick
      if (TRAC_buttonMonitor == LOW && (millis() - TRAC_buttonCounter) > debounce && (millis() - TRAC_buttonCounter) < doubleClick) //second click registered
      {
        TRAC_buttonState = 3; //increment state
      }
      else if ((millis() - TRAC_buttonCounter) > doubleClick)
      {
        digitalWrite (10, LOW); //Transistor off
        TRAC_buttonState = 0; //reset state
      }
      break;

    case 3: //doubleClick made
      if ((millis() - TRAC_buttonCounter) > longClick)
      {
        digitalWrite (10, LOW); //Transistor off
        TRAC_buttonState = 0; //reset state
      }
      break;

    case 4: //initialize after delay by default
      if (millis() > TRAC_initializeDelay)
      {
        digitalWrite (10, HIGH); //Transistor on
        TRAC_buttonCounter = millis(); //start counter
        TRAC_buttonState = 3; //set state to doubleClick
      }
      break;
  }

}


Shiv@Openflash 03-01-2016 09:00 PM

I'm testing ztan's FlexFuel and Speed Density code in my our turbocharged shop car right now. It works brilliantly. You guys are going to be pumped.

myioz86 03-02-2016 12:54 AM

Just wanted to give ztan a big thank you for all the great work he has done for shiv and all of the OFT boosted users.Ztan has put a lot of work into developing the soft wear for us to use.Awsume job

LOLS2K 03-04-2016 01:46 PM

@Takumi788

Wayno 06-02-2016 03:30 AM

So, just to confirm if people are buying commercial flex kits, they should go with the evap option, not rear 02?

Since I have all 10 cranking tables defined in the AU roms, my example roms have these values.

60 x1.05
50 x1.1
40 x1.2
30 x1.3
20 x1.7
10 x1.9
<= 0 x1.5

HLHachiRoku 06-09-2016 09:46 PM

Wow amazing job! I wish I could know the E lvl of our fuel here. I can't wait =D


All times are GMT -4. The time now is 07:32 PM.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
User Alert System provided by Advanced User Tagging v3.3.0 (Lite) - vBulletin Mods & Addons Copyright © 2024 DragonByte Technologies Ltd.


Garage vBulletin Plugins by Drive Thru Online, Inc.