diff --git a/Notice d'utilisation.docx b/Notice d'utilisation.docx
new file mode 100644
index 0000000..ebd9dbd
Binary files /dev/null and b/Notice d'utilisation.docx differ
diff --git a/Shifter STL/Assy.STL b/Shifter STL/Assy.STL
new file mode 100644
index 0000000..ae0d897
Binary files /dev/null and b/Shifter STL/Assy.STL differ
diff --git a/Shifter STL/Center.STL b/Shifter STL/Center.STL
new file mode 100644
index 0000000..c40ad6f
Binary files /dev/null and b/Shifter STL/Center.STL differ
diff --git a/Shifter STL/Center_top.STL b/Shifter STL/Center_top.STL
new file mode 100644
index 0000000..9c96810
Binary files /dev/null and b/Shifter STL/Center_top.STL differ
diff --git a/Shifter STL/Lower_frame.STL b/Shifter STL/Lower_frame.STL
new file mode 100644
index 0000000..d8e84ff
Binary files /dev/null and b/Shifter STL/Lower_frame.STL differ
diff --git a/Shifter STL/Lower_ring.STL b/Shifter STL/Lower_ring.STL
new file mode 100644
index 0000000..3edb0a4
Binary files /dev/null and b/Shifter STL/Lower_ring.STL differ
diff --git a/Shifter STL/Switch_mount.STL b/Shifter STL/Switch_mount.STL
new file mode 100644
index 0000000..c1e3516
Binary files /dev/null and b/Shifter STL/Switch_mount.STL differ
diff --git a/Shifter STL/Upper_frame.STL b/Shifter STL/Upper_frame.STL
new file mode 100644
index 0000000..ee7de6c
Binary files /dev/null and b/Shifter STL/Upper_frame.STL differ
diff --git a/Shifter STL/clamp.STL b/Shifter STL/clamp.STL
new file mode 100644
index 0000000..1cd2677
Binary files /dev/null and b/Shifter STL/clamp.STL differ
diff --git a/SimulatorDescriptor.h b/SimulatorDescriptor.h
new file mode 100644
index 0000000..7c6b1d0
--- /dev/null
+++ b/SimulatorDescriptor.h
@@ -0,0 +1,70 @@
+// D:\Documents\Simulator project\SimulatorDescriptor.h
+
+
+char ReportDescriptor[125] = {
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x09, 0x04, // USAGE (Joystick)
+ 0xa1, 0x01, // COLLECTION (Application)
+ 0x85, 0x03, // REPORT_ID (3)
+ 0x05, 0x09, // USAGE_PAGE (Button)
+ 0x19, 0x01, // USAGE_MINIMUM (Button 1)
+ 0x29, 0x08, // USAGE_MAXIMUM (Button 8)
+ 0x15, 0x00, // LOGICAL_MINIMUM (0)
+ 0x25, 0x01, // LOGICAL_MAXIMUM (1)
+ 0x95, 0x08, // REPORT_COUNT (8)
+ 0x75, 0x01, // REPORT_SIZE (1)
+ 0x81, 0x02, // INPUT (Data,Var,Abs)
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x15, 0x00, // LOGICAL_MINIMUM (0)
+ 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
+ 0xa1, 0x00, // COLLECTION (Physical)
+ 0x09, 0x32, // USAGE (Z)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x81, 0x02, // INPUT (Data,Var,Abs)
+ 0xc0, // END_COLLECTION
+ 0xc0, // END_COLLECTION
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x09, 0x04, // USAGE (Joystick)
+ 0xa1, 0x01, // COLLECTION (Application)
+ 0x85, 0x04, // REPORT_ID (4)
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x15, 0x00, // LOGICAL_MINIMUM (0)
+ 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
+ 0xa1, 0x00, // COLLECTION (Physical)
+ 0x09, 0x33, // USAGE (Rx)
+ 0x09, 0x34, // USAGE (Ry)
+ 0x09, 0x35, // USAGE (Rz)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x95, 0x03, // REPORT_COUNT (3)
+ 0x81, 0x02, // INPUT (Data,Var,Abs)
+ 0xc0, // END_COLLECTION
+ 0xc0, // END_COLLECTION
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x09, 0x04, // USAGE (Joystick)
+ 0xa1, 0x01, // COLLECTION (Application)
+ 0x85, 0x05, // REPORT_ID (5)
+ 0x05, 0x09, // USAGE_PAGE (Button)
+ 0x19, 0x01, // USAGE_MINIMUM (Button 1)
+ 0x29, 0x0b, // USAGE_MAXIMUM (Button 11)
+ 0x15, 0x00, // LOGICAL_MINIMUM (0)
+ 0x25, 0x01, // LOGICAL_MAXIMUM (1)
+ 0x75, 0x01, // REPORT_SIZE (1)
+ 0x95, 0x0b, // REPORT_COUNT (11)
+ 0x81, 0x02, // INPUT (Data,Var,Abs)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x75, 0x05, // REPORT_SIZE (5)
+ 0x81, 0x03, // INPUT (Cnst,Var,Abs)
+ 0x05, 0x02, // USAGE_PAGE (Simulation Controls)
+ 0x15, 0x00, // LOGICAL_MINIMUM (0)
+ 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
+ 0xa1, 0x00, // COLLECTION (Physical)
+ 0x09, 0xc8, // USAGE (Steering)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x81, 0x02, // INPUT (Data,Var,Abs)
+ 0xc0, // END_COLLECTION
+ 0xc0, // END_COLLECTION
+ 0x05, 0x01 // USAGE_PAGE (Generic Desktop)
+};
+
diff --git a/SimulatorDescriptor.hid b/SimulatorDescriptor.hid
new file mode 100644
index 0000000..71eed66
Binary files /dev/null and b/SimulatorDescriptor.hid differ
diff --git a/ZenDrive Simulator/ZenDrive Simulator.ino b/ZenDrive Simulator/ZenDrive Simulator.ino
new file mode 100644
index 0000000..b43cb9f
--- /dev/null
+++ b/ZenDrive Simulator/ZenDrive Simulator.ino
@@ -0,0 +1,137 @@
+// ZenDrive Simulator firmware
+// Copyright (c) 2021 - Valentin Boulanger
+// Version : 1.0.0
+//--------------------------------------------------------------------
+
+#include "ZenDrive.h"
+
+// Pins declaration
+const int SPEEDS_PIN = A0;
+const int HANDBRAKE_PIN = A5;
+const int CLUTCH_PIN = A2;
+const int BRAKE_PIN = A3;
+const int ACCELERATOR_PIN = A4;
+const int DIRECTION_PIN = A1;
+const int LEFT_BLINKER_PIN = 2;
+const int RIGHT_BLINKER_PIN = 3;
+const int WARNING_PIN = 4;
+const int CRUISE_PIN = 5;
+const int CRUISE_UP_PIN = 6;
+const int CRUISE_DOWN_PIN = 7;
+const int STARTER_PIN = 8;
+const int HORN_PIN = 9;
+const int LIGHTS_ON_PIN = 10;
+const int ROAD_LIGHTS_PIN = 11;
+const int HEAD_LIGHTS_PIN = 12;
+const int FOG_LIGHTS_PIN = 13;
+
+void setup() {
+ // Initialize sensors
+ pinMode(SPEEDS_PIN, INPUT_PULLUP);
+ pinMode(HANDBRAKE_PIN, INPUT_PULLUP);
+ pinMode(CLUTCH_PIN, INPUT_PULLUP);
+ pinMode(BRAKE_PIN, INPUT_PULLUP);
+ pinMode(ACCELERATOR_PIN, INPUT_PULLUP);
+ pinMode(DIRECTION_PIN, INPUT_PULLUP);
+ pinMode(LEFT_BLINKER_PIN, INPUT_PULLUP);
+ pinMode(RIGHT_BLINKER_PIN, INPUT_PULLUP);
+ pinMode(WARNING_PIN, INPUT_PULLUP);
+ pinMode(CRUISE_PIN, INPUT_PULLUP);
+ pinMode(CRUISE_UP_PIN, INPUT_PULLUP);
+ pinMode(CRUISE_DOWN_PIN, INPUT_PULLUP);
+ pinMode(STARTER_PIN, INPUT_PULLUP);
+ pinMode(HORN_PIN, INPUT_PULLUP);
+ pinMode(LIGHTS_ON_PIN, INPUT_PULLUP);
+ pinMode(ROAD_LIGHTS_PIN, INPUT_PULLUP);
+ pinMode(HEAD_LIGHTS_PIN, INPUT_PULLUP);
+ pinMode(FOG_LIGHTS_PIN, INPUT_PULLUP);
+
+ // Initialize ZenDrive Library
+ ZenDrive.begin(true);
+
+ //Button shared margin
+ int btnMargin = 5;
+}
+
+void loop() {
+ // Set refresh to false
+ ZenDrive.gearshiftNeedRefresh = false;
+ ZenDrive.pedalsNeedRefresh = false;
+ ZenDrive.wheelNeedRefresh = false;
+
+ /* Gearshift module */
+ //Read speed states on the analog shared pin
+ int value = analogRead(A0);
+ if(value > 900) ZenDrive.switchSpeedR();
+ else if(value > 800) ZenDrive.switchSpeed6();
+ else if(value > 700) ZenDrive.switchSpeed5();
+ else if(value > 600) ZenDrive.switchSpeed4();
+ else if(value > 500) ZenDrive.switchSpeed3();
+ else if(value > 400) ZenDrive.switchSpeed2();
+ else if(value > 300) ZenDrive.switchSpeed1();
+ else ZenDrive.switchNeutral();
+ //Read handbrake
+ ZenDrive.setHandbrake(map(analogRead(HANDBRAKE_PIN), 0, 1023, 0, 255));
+ // Send gearshift states if there are changes
+ if(ZenDrive.gearshiftNeedRefresh) ZenDrive.sendGearshiftStates();
+
+ /* Pedals module */
+ // Read clutch
+ ZenDrive.setClutch(map(analogRead(CLUTCH_PIN), 0, 1023, 0, 255));
+ // Read brake
+ ZenDrive.setBrake(map(analogRead(BRAKE_PIN), 0, 1023, 0, 255));
+ // Read accelerator
+ ZenDrive.setAccelerator(map(analogRead(ACCELERATOR_PIN), 0, 1023, 0, 255));
+ // Send pedals states if they are changes
+ if(ZenDrive.pedalsNeedRefresh) ZenDrive.sendPedalsStates();
+
+ /* Steering wheel module */
+ // Left blinker
+ ZenDrive.setBlinkerLeft(digitalRead(LEFT_BLINKER_PIN));
+ // Right blinker
+ ZenDrive.setBlinkerRight(digitalRead(RIGHT_BLINKER_PIN));
+ // Warning
+ ZenDrive.setWarning(digitalRead(WARNING_PIN));
+ // Lights
+ if (digitalRead(LIGHTS_ON_PIN)) ZenDrive.switchLightsOn();
+ else if(digitalRead(ROAD_LIGHTS_PIN)) ZenDrive.switchRoadLights();
+ else ZenDrive.switchLightsOff();
+ // Head lights
+ ZenDrive.setHeadLights(digitalRead(HEAD_LIGHTS_PIN));
+ // Fog lights
+ ZenDrive.setFogLights(digitalRead(FOG_LIGHTS_PIN));
+ // Starter
+ ZenDrive.setStarter(digitalRead(STARTER_PIN));
+ // Horn
+ ZenDrive.setHorn(digitalRead(HORN_PIN));
+ // Cruise on
+ if(digitalRead(CRUISE_PIN)) ZenDrive.activeCruise();
+ // Cruise up
+ if(digitalRead(CRUISE_UP_PIN)) ZenDrive.increaseCruise();
+ // Cruise down
+ if(digitalRead(CRUISE_DOWN_PIN)) ZenDrive.decreaseCruise();
+ // Read direction
+ ZenDrive.setDirection(map(analogRead(DIRECTION_PIN), 0, 1023, -127, 127));
+ // Send steering wheel states if they are changes
+ if(ZenDrive.wheelNeedRefresh) ZenDrive.sendWheelStates();
+
+ // Read pin value
+ /*int clutchValue = map(analogRead(clutchPin), 0, 1023, 0, 255);
+ if(clutchValue < lastClutchState - 5 || clutchValue > lastClutchState + 5){
+ //Serial.println(clutchValue);
+ ZenDrive.setHandbrake(clutchValue);
+ lastClutchState = clutchValue;
+ }*/
+
+
+ /*for (int index = 0; index < 4; index++)
+ {
+ int currentButtonState = !digitalRead(index + pinToButtonMap);
+ if (currentButtonState != lastButtonState[index])
+ {
+ Joystick.setButton(index, currentButtonState);
+ lastButtonState[index] = currentButtonState;
+ }
+ }*/
+ delay(50);
+}
diff --git a/ZenDrive Simulator/ZenDrive.cpp b/ZenDrive Simulator/ZenDrive.cpp
new file mode 100644
index 0000000..50255a8
--- /dev/null
+++ b/ZenDrive Simulator/ZenDrive.cpp
@@ -0,0 +1,504 @@
+/*
+ ZenDrive.cpp
+
+ Copyright (c) 2021, Valentin Boulanger
+
+ This library is a part of the ZenDrive simulator firmware.
+ Version : 1.0.0
+*/
+
+#include "ZenDrive.h"
+
+#if defined(_USING_HID)
+
+#define GEARSHIFT_REPORT_ID 0x03
+#define GEARSHIFT_STATE_SIZE 2
+
+#define PEDALS_REPORT_ID 0x04
+#define PEDALS_STATE_SIZE 3
+
+#define WHEEL_REPORT_ID 0x05
+#define WHEEL_STATE_SIZE 3
+
+static const uint8_t _hidReportDescriptor[] PROGMEM = {
+
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x09, 0x04, // USAGE (Joystick)
+ 0xa1, 0x01, // COLLECTION (Application)
+ 0x85, GEARSHIFT_REPORT_ID, // REPORT_ID (3)
+ 0x05, 0x09, // USAGE_PAGE (Button)
+ 0x19, 0x01, // USAGE_MINIMUM (Button 1)
+ 0x29, 0x08, // USAGE_MAXIMUM (Button 8)
+ 0x15, 0x00, // LOGICAL_MINIMUM (0)
+ 0x25, 0x01, // LOGICAL_MAXIMUM (1)
+ 0x95, 0x08, // REPORT_COUNT (8)
+ 0x75, 0x01, // REPORT_SIZE (1)
+ 0x81, 0x02, // INPUT (Data,Var,Abs)
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x15, 0x00, // LOGICAL_MINIMUM (0)
+ 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
+ 0xa1, 0x00, // COLLECTION (Physical)
+ 0x09, 0x32, // USAGE (Z)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x81, 0x02, // INPUT (Data,Var,Abs)
+ 0xc0, // END_COLLECTION
+ 0xc0, // END_COLLECTION
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x09, 0x04, // USAGE (Joystick)
+ 0xa1, 0x01, // COLLECTION (Application)
+ 0x85, PEDALS_REPORT_ID, // REPORT_ID (4)
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x15, 0x00, // LOGICAL_MINIMUM (0)
+ 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
+ 0xa1, 0x00, // COLLECTION (Physical)
+ 0x09, 0x33, // USAGE (Rx)
+ 0x09, 0x34, // USAGE (Ry)
+ 0x09, 0x35, // USAGE (Rz)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x95, 0x03, // REPORT_COUNT (3)
+ 0x81, 0x02, // INPUT (Data,Var,Abs)
+ 0xc0, // END_COLLECTION
+ 0xc0, // END_COLLECTION
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x09, 0x04, // USAGE (Joystick)
+ 0xa1, 0x01, // COLLECTION (Application)
+ 0x85, WHEEL_REPORT_ID, // REPORT_ID (5)
+ 0x05, 0x09, // USAGE_PAGE (Button)
+ 0x19, 0x01, // USAGE_MINIMUM (Button 1)
+ 0x29, 0x0b, // USAGE_MAXIMUM (Button 11)
+ 0x15, 0x00, // LOGICAL_MINIMUM (0)
+ 0x25, 0x01, // LOGICAL_MAXIMUM (1)
+ 0x75, 0x01, // REPORT_SIZE (1)
+ 0x95, 0x0b, // REPORT_COUNT (11)
+ 0x81, 0x02, // INPUT (Data,Var,Abs)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x75, 0x05, // REPORT_SIZE (5)
+ 0x81, 0x03, // INPUT (Cnst,Var,Abs)
+ 0x05, 0x02, // USAGE_PAGE (Simulation Controls)
+ 0x15, 0x00, // LOGICAL_MINIMUM (0)
+ 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
+ 0xa1, 0x00, // COLLECTION (Physical)
+ 0x09, 0xc8, // USAGE (Steering)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x81, 0x02, // INPUT (Data,Var,Abs)
+ 0xc0, // END_COLLECTION
+ 0xc0 // END_COLLECTION
+};
+
+ZenDrive_::ZenDrive_()
+{
+ // Setup HID report structure
+ static HIDSubDescriptor node(_hidReportDescriptor, sizeof(_hidReportDescriptor));
+ HID().AppendDescriptor(&node);
+
+ // Initalize state for each module
+ // Gearshift module
+ speeds = B00000001; // (NEUTRAL;SPEED1;SPEED2;SPEED3;SPEED4;SPEED5;SPEED6;SPEEDR)
+ handbrake = 255;
+
+ //Pedals module
+ clutch = 0;
+ brake = 0;
+ accelerator = 0;
+
+ //Steering wheel module
+ wheelCommands = 0; // (BLINKER LEFT;BLINKER RIGHT;WARNING;LIGHTS;HEADLIGHTS;FOGLIGHTS;STARTER;HORN;CRUISE;CRUISE +;CRUISE -;NOT USED;NOT USED;NOT USED;NOT USED;NOT USED)
+ steering = 0;
+}
+
+void ZenDrive_::begin(bool initAutoSendState)
+{
+ // Sending initial states
+ sendGearshiftStates();
+ sendPedalsStates();
+ sendWheelStates();
+}
+
+void ZenDrive_::end()
+{
+}
+
+// Gearshift module
+void ZenDrive_::switchNeutral()
+{
+ if(currentSpeed != 0){
+ bitSet(speeds, 0);
+ bitClear(speeds, 1);
+ bitClear(speeds, 2);
+ bitClear(speeds, 3);
+ bitClear(speeds, 4);
+ bitClear(speeds, 5);
+ bitClear(speeds, 6);
+ bitClear(speeds, 7);
+ currentSpeed = 0;
+ gearshiftNeedRefresh = true;
+ }
+}
+void ZenDrive_::switchSpeed1()
+{
+ if(currentSpeed != 1){
+ bitClear(speeds, 0);
+ bitSet(speeds, 1);
+ bitClear(speeds, 2);
+ bitClear(speeds, 3);
+ bitClear(speeds, 4);
+ bitClear(speeds, 5);
+ bitClear(speeds, 6);
+ bitClear(speeds, 7);
+ currentSpeed = 1;
+ gearshiftNeedRefresh = true;
+ }
+}
+void ZenDrive_::switchSpeed2()
+{
+ if(currentSpeed != 2)
+ {
+ bitClear(speeds, 0);
+ bitClear(speeds, 1);
+ bitSet(speeds, 2);
+ bitClear(speeds, 3);
+ bitClear(speeds, 4);
+ bitClear(speeds, 5);
+ bitClear(speeds, 6);
+ bitClear(speeds, 7);
+ currentSpeed = 2;
+ gearshiftNeedRefresh = true;
+ }
+}
+void ZenDrive_::switchSpeed3()
+{
+ if(currentSpeed != 3)
+ {
+ bitClear(speeds, 0);
+ bitClear(speeds, 1);
+ bitClear(speeds, 2);
+ bitSet(speeds, 3);
+ bitClear(speeds, 4);
+ bitClear(speeds, 5);
+ bitClear(speeds, 6);
+ bitClear(speeds, 7);
+ currentSpeed = 3;
+ gearshiftNeedRefresh = true;
+ }
+}
+void ZenDrive_::switchSpeed4()
+{
+ if(currentSpeed != 4)
+ {
+ bitClear(speeds, 0);
+ bitClear(speeds, 1);
+ bitClear(speeds, 2);
+ bitClear(speeds, 3);
+ bitSet(speeds, 4);
+ bitClear(speeds, 5);
+ bitClear(speeds, 6);
+ bitClear(speeds, 7);
+ currentSpeed = 4;
+ gearshiftNeedRefresh = true;
+ }
+}
+void ZenDrive_::switchSpeed5()
+{
+ if(currentSpeed != 5)
+ {
+ bitClear(speeds, 0);
+ bitClear(speeds, 1);
+ bitClear(speeds, 2);
+ bitClear(speeds, 3);
+ bitClear(speeds, 4);
+ bitSet(speeds, 5);
+ bitClear(speeds, 6);
+ bitClear(speeds, 7);
+ currentSpeed = 5;
+ gearshiftNeedRefresh = true;
+ }
+}
+void ZenDrive_::switchSpeed6()
+{
+ if(currentSpeed != 6)
+ {
+ bitClear(speeds, 0);
+ bitClear(speeds, 1);
+ bitClear(speeds, 2);
+ bitClear(speeds, 3);
+ bitClear(speeds, 4);
+ bitClear(speeds, 5);
+ bitSet(speeds, 6);
+ bitClear(speeds, 7);
+ currentSpeed = 6;
+ gearshiftNeedRefresh = true;
+ }
+}
+void ZenDrive_::switchSpeedR()
+{
+ if(currentSpeed != 7)
+ {
+ bitClear(speeds, 0);
+ bitClear(speeds, 1);
+ bitClear(speeds, 2);
+ bitClear(speeds, 3);
+ bitClear(speeds, 4);
+ bitClear(speeds, 5);
+ bitClear(speeds, 6);
+ bitSet(speeds, 7);
+ currentSpeed = 7;
+ gearshiftNeedRefresh = true;
+ }
+}
+
+void ZenDrive_::setHandbrake(int8_t value)
+{
+ if(value < handbrake - 5 || value > handbrake + 5)
+ {
+ handbrake = value;
+ gearshiftNeedRefresh = true;
+ }
+}
+
+// Pedals module
+void ZenDrive_::setClutch(int8_t value)
+{
+ if(value < clutch - 5 || value > clutch + 5)
+ {
+ clutch = value;
+ pedalsNeedRefresh = true;
+ }
+}
+
+void ZenDrive_::setBrake(int8_t value)
+{
+ if(value < brake - 5 || value > brake + 5)
+ {
+ brake = value;
+ pedalsNeedRefresh = true;
+ }
+
+}
+
+void ZenDrive_::setAccelerator(int8_t value)
+{
+ if(value < accelerator - 5 || value > accelerator + 5)
+ {
+ accelerator = value;
+ pedalsNeedRefresh = true;
+ }
+}
+
+// Steering wheel module
+void ZenDrive_::setBlinkerLeft(bool value)
+{
+ if(value != isBlinkerLeft)
+ {
+ bitSet(wheelCommands, 0);
+ sendWheelStates();
+ bitClear(wheelCommands, 0);
+ sendWheelStates();
+ isBlinkerLeft = !isBlinkerLeft;
+ }
+}
+
+void ZenDrive_::setBlinkerRight(bool value)
+{
+ if(value != isBlinkerRight)
+ {
+ bitSet(wheelCommands, 1);
+ sendWheelStates();
+ bitClear(wheelCommands, 1);
+ sendWheelStates();
+ isBlinkerRight = !isBlinkerRight;
+ }
+}
+
+void ZenDrive_::setWarning(bool value)
+{
+ if(value != isWarning)
+ {
+ bitSet(wheelCommands, 2);
+ sendWheelStates();
+ bitClear(wheelCommands, 2);
+ sendWheelStates();
+ isWarning = !isWarning;
+ }
+}
+
+void ZenDrive_::switchLightsOn()
+{
+ int steps = 0;
+ if(isRoadLights) steps = 2;
+ else if(!isLights) steps = 1;
+ if(steps != 0){
+ for(int i = 0; i < steps; i++){
+ bitSet(wheelCommands, 3);
+ sendWheelStates();
+ bitClear(wheelCommands, 3);
+ sendWheelStates();
+ isLights = true;
+ isRoadLights = false;
+ }
+ }
+}
+
+void ZenDrive_::switchRoadLights()
+{
+ int steps = 0;
+ if(isLights) steps = 1;
+ else if(!isRoadLights) steps = 2;
+ if(steps != 0){
+ for(int i = 0; i < steps; i++){
+ bitSet(wheelCommands, 3);
+ sendWheelStates();
+ bitClear(wheelCommands, 3);
+ sendWheelStates();
+ isLights = false;
+ isRoadLights = true;
+ }
+ }
+}
+
+void ZenDrive_::switchLightsOff()
+{
+ int steps = 0;
+ if(isLights) steps = 2;
+ else if(isRoadLights) steps = 1;
+ if(steps != 0){
+ for(int i = 0; i < steps; i++){
+ bitSet(wheelCommands, 3);
+ sendWheelStates();
+ bitClear(wheelCommands, 3);
+ sendWheelStates();
+ isLights = false;
+ isRoadLights = false;
+ }
+ }
+}
+
+void ZenDrive_::setHeadLights(bool value)
+{
+ if(value != isHeadLights)
+ {
+ bitSet(wheelCommands, 4);
+ sendWheelStates();
+ bitClear(wheelCommands, 4);
+ sendWheelStates();
+ isHeadLights = !isHeadLights;
+ }
+}
+
+void ZenDrive_::setFogLights(bool value)
+{
+ if(value != isFogLights)
+ {
+ bitSet(wheelCommands, 5);
+ sendWheelStates();
+ bitClear(wheelCommands, 5);
+ sendWheelStates();
+ isFogLights = !isFogLights;
+ }
+}
+
+void ZenDrive_::setStarter(bool value)
+{
+ if(value != isStarter)
+ {
+ bitSet(wheelCommands, 6);
+ sendWheelStates();
+ bitClear(wheelCommands, 6);
+ sendWheelStates();
+ isStarter = !isStarter;
+ }
+}
+
+void ZenDrive_::setHorn(bool value)
+{
+ if(value != isHorn)
+ {
+ if(value) bitSet(wheelCommands, 7);
+ else bitClear(wheelCommands, 7);
+ wheelNeedRefresh = true;
+ }
+}
+
+void ZenDrive_::activeCruise()
+{
+ bitSet(wheelCommands, 8);
+ sendWheelStates();
+ bitClear(wheelCommands, 8);
+ sendWheelStates();
+}
+
+void ZenDrive_::increaseCruise()
+{
+ bitSet(wheelCommands, 9);
+ sendWheelStates();
+ bitClear(wheelCommands, 9);
+ sendWheelStates();
+}
+
+void ZenDrive_::decreaseCruise()
+{
+ bitSet(wheelCommands, 10);
+ sendWheelStates();
+ bitClear(wheelCommands, 10);
+ sendWheelStates();
+}
+
+void ZenDrive_::setDirection(uint8_t value)
+{
+ if(value < steering - 5 || value > steering + 5)
+ {
+ steering = value;
+ wheelNeedRefresh = true;
+ }
+}
+
+// Send states to the PC
+void ZenDrive_::sendGearshiftStates()
+{
+ // Gearshift module
+ uint8_t dataGearshift[GEARSHIFT_STATE_SIZE];
+ uint8_t speedTmp = speeds;
+ dataGearshift[0] = speedTmp & 0xFF;
+ dataGearshift[1] = handbrake;
+
+ HID().SendReport(GEARSHIFT_REPORT_ID, dataGearshift, GEARSHIFT_STATE_SIZE);
+}
+
+void ZenDrive_::sendPedalsStates()
+{
+ // Pedals module
+ uint8_t dataPedals[PEDALS_STATE_SIZE];
+ dataPedals[0] = clutch;
+ dataPedals[1] = brake;
+ dataPedals[2] = accelerator;
+
+ HID().SendReport(PEDALS_REPORT_ID, dataPedals, PEDALS_STATE_SIZE);
+}
+
+void ZenDrive_::sendWheelStates()
+{
+ // Steering wheel module
+ uint8_t dataWheel[WHEEL_STATE_SIZE];
+ uint16_t commandTmp = wheelCommands;
+
+ // Split 16 bit button-state into 2 bytes
+ dataWheel[0] = commandTmp & 0xFF;
+ commandTmp >>= 8;
+ dataWheel[1] = commandTmp & 0xFF;
+ dataWheel[2] = steering;
+
+ HID().SendReport(WHEEL_REPORT_ID, dataWheel, WHEEL_STATE_SIZE);
+
+ /*data[7] = xAxis + 127;
+ data[8] = yAxis + 127;
+ data[9] = zAxis + 127;
+
+ data[10] = (xAxisRotation % 360) * 0.708;
+ data[11] = (yAxisRotation % 360) * 0.708;
+ data[12] = (zAxisRotation % 360) * 0.708;*/
+}
+
+ZenDrive_ ZenDrive;
+
+#endif
diff --git a/ZenDrive Simulator/ZenDrive.h b/ZenDrive Simulator/ZenDrive.h
new file mode 100644
index 0000000..7125d62
--- /dev/null
+++ b/ZenDrive Simulator/ZenDrive.h
@@ -0,0 +1,111 @@
+/*
+ ZenDrive.h
+
+ Copyright (c) 2021, Valentin Boulanger
+
+ This library is a part of the ZenDrive simulator firmware.
+ Version : 1.0.0
+*/
+
+#ifndef ZENDRIVE_h
+#define ZENDRIVE_h
+
+#include "HID.h"
+
+#if ARDUINO < 10606
+#error The ZenDrive library requires Arduino IDE 1.6.6 or greater. Please update your IDE.
+#endif
+
+#if ARDUINO > 10606
+#if !defined(USBCON)
+#error The ZenDrive library can only be used with a USB MCU (e.g. Arduino Leonardo, Arduino Micro, etc.).
+#endif
+#endif
+
+#if !defined(_USING_HID)
+
+#warning "Using legacy HID core (non pluggable)"
+
+#else
+
+//================================================================================
+//================================================================================
+// ZenDrive Simulator (Gamepad)
+
+class ZenDrive_
+{
+private:
+
+ // Gearshift module
+ uint8_t speeds; // (NEUTRAL;SPEED1;SPEED2;SPEED3;SPEED4;SPEED5;SPEED6;SPEEDR)
+ uint8_t handbrake;
+
+ //Pedals module
+ uint8_t clutch;
+ uint8_t brake;
+ uint8_t accelerator;
+
+ //Steering wheel module
+ uint16_t wheelCommands; // (BLINKER LEFT;BLINKER RIGHT;WARNING;LIGHTS;HEAD LIGHTS;FOGLIGHTS;STARTER;HORN;CRUISE;CRUISE +;CRUISE -;NOT USED;NOT USED;NOT USED;NOT USED;NOT USED)
+ int8_t steering;
+
+public:
+ ZenDrive_();
+
+ void begin(bool initAutoSendState = true);
+ void end();
+
+ // Gearshift module
+ bool gearshiftNeedRefresh = false;
+ int currentSpeed = 0;
+ void switchNeutral();
+ void switchSpeed1();
+ void switchSpeed2();
+ void switchSpeed3();
+ void switchSpeed4();
+ void switchSpeed5();
+ void switchSpeed6();
+ void switchSpeedR();
+ int currentHandbrake = 0;
+ void setHandbrake(int8_t value);
+
+ // Pedals module
+ bool pedalsNeedRefresh = false;
+ void setClutch(int8_t value);
+ void setBrake(int8_t value);
+ void setAccelerator(int8_t value);
+
+ // Steering wheel module
+ bool wheelNeedRefresh = false;
+ bool isBlinkerLeft = false;
+ void setBlinkerLeft(bool value);
+ bool isBlinkerRight = false;
+ void setBlinkerRight(bool value);
+ bool isWarning = false;
+ void setWarning(bool value);
+ bool isLights = false;
+ bool isRoadLights = false;
+ void switchLightsOn();
+ void switchRoadLights();
+ void switchLightsOff();
+ bool isHeadLights = false;
+ void setHeadLights(bool value);
+ bool isFogLights = false;
+ void setFogLights(bool value);
+ bool isStarter = false;
+ void setStarter(bool value);
+ bool isHorn = false;
+ void setHorn(bool value);
+ void activeCruise();
+ void increaseCruise();
+ void decreaseCruise();
+ void setDirection(uint8_t value);
+
+ void sendGearshiftStates();
+ void sendPedalsStates();
+ void sendWheelStates();
+};
+extern ZenDrive_ ZenDrive;
+
+#endif
+#endif
diff --git a/logo.ai b/logo.ai
new file mode 100644
index 0000000..c550b93
--- /dev/null
+++ b/logo.ai
@@ -0,0 +1,2029 @@
+%PDF-1.5
%
+1 0 obj
<>/OCGs[25 0 R]>>/Pages 3 0 R/Type/Catalog>>
endobj
2 0 obj
<>stream
+
+
+
+
+ application/pdf
+
+
+ logo
+
+
+ Adobe Illustrator 24.0 (Windows)
+ 2021-01-20T21:16:08+02:00
+ 2021-01-20T21:16:10+01:00
+ 2021-01-20T21:16:10+01:00
+
+
+
+ 256
+ 140
+ JPEG
+ /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA
AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK
DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f
Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgAjAEAAwER
AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA
AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB
UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE
1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ
qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy
obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp
0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo
+DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXYq7FXYq7FXYq7
FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FULqGq
afp0BnvriO2hHWSVlRRX3YgZGUhEWW7DgnlPDAGR8t1S0vLW7hWe2lWaFxVJEIZSD3BGEEHkwyY5
QNSFFWwsHYq82/NH82D5OuLW2htPrdxcBm4luChVIBJajePhmBq9Z4VCrer9nvZz8+JSMuGMfK2V
eR/NUPmjy7a6vEhjWcGsbdVZWKMPoZTmTgzDJASdN2t2dLR55Yib4f7U/wAuda7FXYq7FXYq7FXY
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
dirsVdirsVdirsVdirsVdirsVdirsVdirsVdiriMVQd3bh1O2RIbscqYbr+lqyt8PbMecXc6XPT5
x8++WW0HWmkiSmm3zFoqdI5urR+wb7S/Tmn1eH+IPo3s92lY8KR9yl5I80SeXNbV5Hppl6yx3Y7R
v0Sb+De3yx0mavSU+0XZvEPFiPf+t9LaBqnMJ8Va5uISfNtVhpmFpNzUZkAuoyRpFjJNLsVdirsV
dirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVWutRikFKdSsw6Hbtlcg5e
HJReaeevKttqunXFlOvwSj4XA+JWG6svup3zEywt6HQ6kxIIfOc0LRXF1YXBV57SR7efjupZCVJH
zzR5cZhJ9S7P1cdVh358pIaP8wPPnla+jksNWnaCKnpwXDGaEoNuBR60G1PhofDNrpc3EHgu3ezj
gyEfwnk+sfye/MO188eVYdWiT0LmNjb39sDURzoAWAP8rBgy+xzYwLxmeNF6KhqMtcErsUOxV2Ku
xV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxVRmjDKcBZxLHtX04SKds
qnF2GnzU+IvNL3mg+ftctL1CjpezMyn9qORzIjD/AFkYMM1+owcYet7H7W8CYP8AD1SvzFrFndW6
Rw7kGpYilPbKdJp5QNl2ftD2vh1GMRh06voj/nD7S7+HyvrOoyhltL28VLUEUDejHSR18QS/H5qc
20A+e6iW76Nj6Za4BX4WLsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdir
sVdirsVcRXFULcW6uOmRIbYTp5f+aH5F+WvPJS5nL2GrRLwj1CAKWK9llQ7SKO24I8crMHLhnIed
6P8A84eadHfRyax5imvrNSC9tBbC2ZqdjIZZ6A+y1xEGctQS+hfL+g6boumW2mabbra2Fogjt4E+
yqj57n3J3OWAOHOdpwopkmkt4odirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsV
dirsVdirsVdirsVcRiqwxqcDK2hEuNLxLwoGFFt4odirsVdirsVdirsVdirsVdirsVdirsVdirsV
dirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVd
irsVdirsVdirsVdirsVdir//2Q==
+
+
+
+ proof:pdf
+ uuid:65E6390686CF11DBA6E2D887CEACB407
+ xmp.did:29febeb8-be1e-ca4c-9a01-7e07c6e43ba0
+ uuid:e31e14f2-aa4d-46fa-ae38-96daa47b2183
+
+ xmp.iid:aae2460b-0e68-d842-ba5e-4675e5d854a2
+ xmp.did:aae2460b-0e68-d842-ba5e-4675e5d854a2
+ uuid:65E6390686CF11DBA6E2D887CEACB407
+ default
+
+
+
+
+ saved
+ xmp.iid:a4415359-4822-594a-97d4-5b82eb84525b
+ 2021-01-20T19:08:11+01:00
+ Adobe Illustrator 24.0 (Windows)
+ /
+
+
+ saved
+ xmp.iid:29febeb8-be1e-ca4c-9a01-7e07c6e43ba0
+ 2021-01-20T20:19:12+01:00
+ Adobe Illustrator 24.0 (Windows)
+ /
+
+
+
+ Web
+ AIRobin
+ Document
+ 1
+ True
+ False
+
+ 500.000000
+ 500.000000
+ Pixels
+
+
+
+ Cyan
+ Magenta
+ Yellow
+ Black
+
+
+
+
+
+ Groupe de nuances par défaut
+ 0
+
+
+
+ Blanc
+ RGB
+ PROCESS
+ 255
+ 255
+ 255
+
+
+ Noir
+ RGB
+ PROCESS
+ 0
+ 0
+ 0
+
+
+ Rouge RVB
+ RGB
+ PROCESS
+ 255
+ 0
+ 0
+
+
+ Jaune RVB
+ RGB
+ PROCESS
+ 255
+ 255
+ 0
+
+
+ Vert RVB
+ RGB
+ PROCESS
+ 0
+ 255
+ 0
+
+
+ Cyan RVB
+ RGB
+ PROCESS
+ 0
+ 255
+ 255
+
+
+ Bleu RVB
+ RGB
+ PROCESS
+ 0
+ 0
+ 255
+
+
+ Magenta RVB
+ RGB
+ PROCESS
+ 255
+ 0
+ 255
+
+
+ R=193 V=39 B=45
+ RGB
+ PROCESS
+ 193
+ 39
+ 45
+
+
+ R=237 V=28 B=36
+ RGB
+ PROCESS
+ 237
+ 28
+ 36
+
+
+ R=241 V=90 B=36
+ RGB
+ PROCESS
+ 241
+ 90
+ 36
+
+
+ R=247 V=147 B=30
+ RGB
+ PROCESS
+ 247
+ 147
+ 30
+
+
+ R=251 V=176 B=59
+ RGB
+ PROCESS
+ 251
+ 176
+ 59
+
+
+ R=252 V=238 B=33
+ RGB
+ PROCESS
+ 252
+ 238
+ 33
+
+
+ R=217 V=224 B=33
+ RGB
+ PROCESS
+ 217
+ 224
+ 33
+
+
+ R=140 V=198 B=63
+ RGB
+ PROCESS
+ 140
+ 198
+ 63
+
+
+ R=57 V=181 B=74
+ RGB
+ PROCESS
+ 57
+ 181
+ 74
+
+
+ R=0 V=146 B=69
+ RGB
+ PROCESS
+ 0
+ 146
+ 69
+
+
+ R=0 V=104 B=55
+ RGB
+ PROCESS
+ 0
+ 104
+ 55
+
+
+ R=34 V=181 B=115
+ RGB
+ PROCESS
+ 34
+ 181
+ 115
+
+
+ R=0 V=69 B=157
+ RGB
+ PROCESS
+ 0
+ 169
+ 157
+
+
+ R=41 V=71 B=226
+ RGB
+ PROCESS
+ 41
+ 171
+ 226
+
+
+ R=0 V=113 B=188
+ RGB
+ PROCESS
+ 0
+ 113
+ 188
+
+
+ R=46 V=49 B=146
+ RGB
+ PROCESS
+ 46
+ 49
+ 146
+
+
+ R=27 V=20 B=100
+ RGB
+ PROCESS
+ 27
+ 20
+ 100
+
+
+ R=102 V=45 B=145
+ RGB
+ PROCESS
+ 102
+ 45
+ 145
+
+
+ R=147 V=39 B=143
+ RGB
+ PROCESS
+ 147
+ 39
+ 143
+
+
+ R=158 V=0 B=93
+ RGB
+ PROCESS
+ 158
+ 0
+ 93
+
+
+ R=212 V=20 B=90
+ RGB
+ PROCESS
+ 212
+ 20
+ 90
+
+
+ R=237 V=30 B=121
+ RGB
+ PROCESS
+ 237
+ 30
+ 121
+
+
+ R=199 V=178 B=153
+ RGB
+ PROCESS
+ 199
+ 178
+ 153
+
+
+ R=153 V=134 B=117
+ RGB
+ PROCESS
+ 153
+ 134
+ 117
+
+
+ R=115 V=99 B=87
+ RGB
+ PROCESS
+ 115
+ 99
+ 87
+
+
+ R=83 V=71 B=65
+ RGB
+ PROCESS
+ 83
+ 71
+ 65
+
+
+ R=198 V=156 B=109
+ RGB
+ PROCESS
+ 198
+ 156
+ 109
+
+
+ R=166 V=124 B=82
+ RGB
+ PROCESS
+ 166
+ 124
+ 82
+
+
+ R=140 V=98 B=57
+ RGB
+ PROCESS
+ 140
+ 98
+ 57
+
+
+ R=117 V=76 B=36
+ RGB
+ PROCESS
+ 117
+ 76
+ 36
+
+
+ R=96 V=56 B=19
+ RGB
+ PROCESS
+ 96
+ 56
+ 19
+
+
+ R=66 V=33 B=11
+ RGB
+ PROCESS
+ 66
+ 33
+ 11
+
+
+
+
+
+ Gris
+ 1
+
+
+
+ R=0 V=0 B=0
+ RGB
+ PROCESS
+ 0
+ 0
+ 0
+
+
+ R=26 V=26 B=26
+ RGB
+ PROCESS
+ 26
+ 26
+ 26
+
+
+ R=51 V=51 B=51
+ RGB
+ PROCESS
+ 51
+ 51
+ 51
+
+
+ R=77 V=77 B=77
+ RGB
+ PROCESS
+ 77
+ 77
+ 77
+
+
+ R=102 V=102 B=102
+ RGB
+ PROCESS
+ 102
+ 102
+ 102
+
+
+ R=128 V=128 B=128
+ RGB
+ PROCESS
+ 128
+ 128
+ 128
+
+
+ R=153 V=153 B=153
+ RGB
+ PROCESS
+ 153
+ 153
+ 153
+
+
+ R=179 V=179 B=179
+ RGB
+ PROCESS
+ 179
+ 179
+ 179
+
+
+ R=204 V=204 B=204
+ RGB
+ PROCESS
+ 204
+ 204
+ 204
+
+
+ R=230 V=230 B=230
+ RGB
+ PROCESS
+ 230
+ 230
+ 230
+
+
+ R=242 V=242 B=242
+ RGB
+ PROCESS
+ 242
+ 242
+ 242
+
+
+
+
+
+ Groupe de couleurs Web
+ 1
+
+
+
+ R=63 V=169 B=245
+ RGB
+ PROCESS
+ 63
+ 169
+ 245
+
+
+ R=122 V=201 B=67
+ RGB
+ PROCESS
+ 122
+ 201
+ 67
+
+
+ R=255 V=147 B=30
+ RGB
+ PROCESS
+ 255
+ 147
+ 30
+
+
+ R=255 V=29 B=37
+ RGB
+ PROCESS
+ 255
+ 29
+ 37
+
+
+ R=255 V=123 B=172
+ RGB
+ PROCESS
+ 255
+ 123
+ 172
+
+
+ R=189 V=204 B=212
+ RGB
+ PROCESS
+ 189
+ 204
+ 212
+
+
+
+
+
+
+ Adobe PDF library 15.00
+ 21.0.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+endstream
endobj
3 0 obj
<>
endobj
5 0 obj
<>/Resources<>/ExtGState<>/ProcSet[/PDF/ImageC/ImageI]/Properties<>/XObject<>>>/TrimBox[0.0 0.0 500.0 500.0]/Type/Page>>
endobj
27 0 obj
<>/Resources<>/ExtGState<>/Properties<>>>/TrimBox[0.0 0.0 500.0 500.0]/Type/Page>>
endobj
44 0 obj
<>stream
+HTIn0@dkܢ|.'@C_js|&&G3m4i<>M7txa5N3p^8E^nRֲʇ1rcb7
+XpT&J~0+WX0Atf,W WlD*R+ilyMPq/
Eu\f8ףH~tݘ'?*7xlDEb݊)܊)C6\XFedEγ*:.y6PqVi)|lGKlhN%8ԧbBc/6[ "rbv+G&ڟ !Nyz>ɿ
+endstream
endobj
45 0 obj
<>
endobj
25 0 obj
<>
endobj
47 0 obj
[/View/Design]
endobj
48 0 obj
<>>>
endobj
32 0 obj
<>
endobj
30 0 obj
[/ICCBased 49 0 R]
endobj
49 0 obj
<>stream
+HyTSwoɞc
[5laQIBHADED2mtFOE.c}088GNg9w߽ '0 ֠Jb
+ 2y.-;!KZ ^i"L0-
@8(r;q7Ly&Qq4j|9
+V)gB0iW8#8wթ8_٥ʨQQj@&A)/g>'K t;\
ӥ$պFZUn(4T%)뫔0C&Zi8bxEB;Pӓ̹Aom?W=
+x- [ 0}y)7ta>jT7@tܛ`q2ʀ&6ZLĄ?_yxg)˔zçLU*uSkSeO4?c. R
߁-25 S>ӣVd`rn~Y&+`;A4 A9 =-tl`;~p Gp| [`L`< "AYA+Cb(R, *T2B-
+ꇆnQt}MA0alSx k&^>0|>_',G!"F$H:R!zFQd?r9\A&GrQhE]a4zBgE#H *B=0HIpp0MxJ$D1D, VĭKĻYdE"EI2EBGt4MzNr!YK ?%_(0J:EAiQ(()ӔWT6U@P+!~mDeԴ!hӦh/']B/ҏӿ?a0nhF!X8܌kc&5S6lIa2cKMA!E#ƒdV(kel
}}Cq9
+N')].uJr
+wG xR^[oƜchg`>b$*~ :Eb~,m,-ݖ,Y¬*6X[ݱF=3뭷Y~dó tizf6~`{v.Ng#{}}jc1X6fm;'_9 r:8q:˜O:ϸ8uJqnv=MmR 4
+n3ܣkGݯz=[==<=GTB(/S,]6*-W:#7*e^YDY}UjAyT`#D="b{ų+ʯ:!kJ4Gmt}uC%K7YVfFY.=b?SƕƩȺy
چk5%4m7lqlioZlG+Zzmzy]?uuw|"űNwW&e֥ﺱ*|j5kyݭǯg^ykEklD_p߶7Dmo꿻1ml{Mś
nLl<9O [$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD- u`ֲK³8%yhYѹJº;.!
+zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs
2F[p(@Xr4Pm8Ww)Km
+endstream
endobj
8 0 obj
<>
endobj
18 0 obj
<>
endobj
19 0 obj
<>stream
+%!PS-Adobe-3.0
+%%Creator: Adobe Illustrator(R) 24.0
+%%AI8_CreatorVersion: 24.0.0
+%%For: (Valentin Boulanger) ()
+%%Title: (logo.ai)
+%%CreationDate: 1/20/2021 9:16 PM
+%%Canvassize: 16383
+%%BoundingBox: 2 -490 877 -15
+%%HiResBoundingBox: 2 -490 876.5 -15.4999999999991
+%%DocumentProcessColors: Cyan Magenta Yellow Black
+%AI5_FileFormat 14.0
+%AI12_BuildNumber: 330
+%AI3_ColorUsage: Color
+%AI7_ImageSettings: 0
+%%RGBProcessColor: 0 0 0 ([Repérage])
+%AI3_Cropmarks: 520 -500 1020 0
+%AI3_TemplateBox: 250.5 -250.5 250.5 -250.5
+%AI3_TileBox: 472.362213134766 -670.97509765625 1067.68222045898 170.944885253906
+%AI3_DocumentPreview: None
+%AI5_ArtSize: 14400 14400
+%AI5_RulerUnits: 6
+%AI9_ColorModel: 1
+%AI5_ArtFlags: 0 0 0 1 0 0 1 0 0
+%AI5_TargetResolution: 800
+%AI5_NumLayers: 1
+%AI9_OpenToView: 333.04347826087 1.35869565217308 1.84 1616 958 18 0 0 46 87 0 0 0 1 1 0 1 1 0 0
+%AI5_OpenViewLayers: 7
+%%PageOrigin:-150 -550
+%AI7_GridSettings: 72 8 72 8 1 0 0.800000011920929 0.800000011920929 0.800000011920929 0.899999976158142 0.899999976158142 0.899999976158142
+%AI9_Flatten: 1
+%AI12_CMSettings: 00.MS
+%%EndComments
+
+endstream
endobj
20 0 obj
<>stream
+%AI24_ZStandard_Data(/ Xd~E9 o0 T)Rlt.}=y'ֽ>GcҲ2
+8X9-hWUv7TNˬu