example of display BMI160 on oled

Dependencies:   BMI160 max32630fthr Adafruit_FeatherOLED USBDevice

Committer:
bangclever
Date:
Sun Jun 14 20:17:43 2020 +0000
Revision:
11:6fdec00dbb90
Parent:
10:1f5e78dd4a7c
oled + BMI

Who changed what in which revision?

UserRevisionLine numberNew contents of line
switches 9:ecdad18f61c2 1 /**********************************************************************
switches 9:ecdad18f61c2 2 * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
switches 9:ecdad18f61c2 3 *
switches 9:ecdad18f61c2 4 * Permission is hereby granted, free of charge, to any person obtaining a
switches 9:ecdad18f61c2 5 * copy of this software and associated documentation files (the "Software"),
switches 9:ecdad18f61c2 6 * to deal in the Software without restriction, including without limitation
switches 9:ecdad18f61c2 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
switches 9:ecdad18f61c2 8 * and/or sell copies of the Software, and to permit persons to whom the
switches 9:ecdad18f61c2 9 * Software is furnished to do so, subject to the following conditions:
switches 9:ecdad18f61c2 10 *
switches 9:ecdad18f61c2 11 * The above copyright notice and this permission notice shall be included
switches 9:ecdad18f61c2 12 * in all copies or substantial portions of the Software.
switches 9:ecdad18f61c2 13 *
switches 9:ecdad18f61c2 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
switches 9:ecdad18f61c2 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
switches 9:ecdad18f61c2 16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
switches 9:ecdad18f61c2 17 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
switches 9:ecdad18f61c2 18 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
switches 9:ecdad18f61c2 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
switches 9:ecdad18f61c2 20 * OTHER DEALINGS IN THE SOFTWARE.
switches 9:ecdad18f61c2 21 *
switches 9:ecdad18f61c2 22 * Except as contained in this notice, the name of Maxim Integrated
switches 9:ecdad18f61c2 23 * Products, Inc. shall not be used except as stated in the Maxim Integrated
switches 9:ecdad18f61c2 24 * Products, Inc. Branding Policy.
switches 9:ecdad18f61c2 25 *
switches 9:ecdad18f61c2 26 * The mere transfer of this software does not imply any licenses
switches 9:ecdad18f61c2 27 * of trade secrets, proprietary technology, copyrights, patents,
switches 9:ecdad18f61c2 28 * trademarks, maskwork rights, or any other form of intellectual
switches 9:ecdad18f61c2 29 * property whatsoever. Maxim Integrated Products, Inc. retains all
switches 9:ecdad18f61c2 30 * ownership rights.
switches 9:ecdad18f61c2 31 **********************************************************************/
switches 9:ecdad18f61c2 32
switches 0:60a522ae2e35 33 #include "mbed.h"
switches 2:57500e991166 34 #include "max32630fthr.h"
switches 8:1d48f139567d 35 #include "Adafruit_SSD1306.h"
switches 1:6923b075c8d7 36 #include "USBSerial.h"
bangclever 11:6fdec00dbb90 37 #include "bmi160.h"
bangclever 11:6fdec00dbb90 38
switches 0:60a522ae2e35 39
switches 6:684c51f32c1d 40 MAX32630FTHR pegasus(MAX32630FTHR::VIO_3V3);
switches 0:60a522ae2e35 41
switches 8:1d48f139567d 42 I2C i2c(P3_4, P3_5); // SDA, SCL
switches 8:1d48f139567d 43
switches 1:6923b075c8d7 44 // Hardware serial port over DAPLink
switches 2:57500e991166 45 Serial daplink(P2_1, P2_0);
switches 1:6923b075c8d7 46
switches 3:601c11238ccb 47 // Virtual serial port over USB
switches 3:601c11238ccb 48 USBSerial microUSB;
switches 3:601c11238ccb 49
switches 2:57500e991166 50 DigitalOut rLED(LED1);
switches 2:57500e991166 51 DigitalOut gLED(LED2);
switches 2:57500e991166 52 DigitalOut bLED(LED3);
bangclever 11:6fdec00dbb90 53
switches 0:60a522ae2e35 54
switches 9:ecdad18f61c2 55 DigitalIn aButton(P5_3, PullUp);
switches 9:ecdad18f61c2 56 DigitalIn bButton(P3_3, PullUp);
switches 9:ecdad18f61c2 57 DigitalIn cButton(P3_2, PullUp);
switches 9:ecdad18f61c2 58
switches 9:ecdad18f61c2 59 /* Analog inputs 0 and 1 have internal dividers to allow measuring 5V signals
switches 9:ecdad18f61c2 60 * The dividers are selected by using inputs AIN_5 and AIN_5 respectively.
switches 9:ecdad18f61c2 61 * The full scale range for AIN0-3 is 1.2V
switches 9:ecdad18f61c2 62 * The full scale range for AIN4-5 is 6.0V
switches 9:ecdad18f61c2 63 */
switches 9:ecdad18f61c2 64 AnalogIn ain0(AIN_4);
switches 9:ecdad18f61c2 65 AnalogIn ain1(AIN_5);
switches 9:ecdad18f61c2 66 AnalogIn ain2(AIN_2);
switches 8:1d48f139567d 67 AnalogIn ain3(AIN_3);
bangclever 11:6fdec00dbb90 68 // main() runs in its own thread in the OS
bangclever 11:6fdec00dbb90 69 // (note the calls to Thread::wait below for delays)
bangclever 11:6fdec00dbb90 70
bangclever 11:6fdec00dbb90 71
bangclever 11:6fdec00dbb90 72 Timer t;
bangclever 11:6fdec00dbb90 73
bangclever 11:6fdec00dbb90 74 //*****************************************************************************
bangclever 11:6fdec00dbb90 75
bangclever 11:6fdec00dbb90 76 void dumpImuRegisters(BMI160 &imu);
bangclever 11:6fdec00dbb90 77 void printRegister(BMI160 &imu, BMI160::Registers reg);
bangclever 11:6fdec00dbb90 78 void printBlock(BMI160 &imu, BMI160::Registers startReg, BMI160::Registers stopReg);
bangclever 11:6fdec00dbb90 79
bangclever 11:6fdec00dbb90 80
bangclever 11:6fdec00dbb90 81
bangclever 11:6fdec00dbb90 82 void dumpImuRegisters(BMI160 &imu)
bangclever 11:6fdec00dbb90 83 {
bangclever 11:6fdec00dbb90 84 printRegister(imu, BMI160::CHIP_ID);
bangclever 11:6fdec00dbb90 85 printBlock(imu, BMI160::ERR_REG,BMI160::FIFO_DATA);
bangclever 11:6fdec00dbb90 86 printBlock(imu, BMI160::ACC_CONF, BMI160::FIFO_CONFIG_1);
bangclever 11:6fdec00dbb90 87 printBlock(imu, BMI160::MAG_IF_0, BMI160::SELF_TEST);
bangclever 11:6fdec00dbb90 88 printBlock(imu, BMI160::NV_CONF, BMI160::STEP_CONF_1);
bangclever 11:6fdec00dbb90 89 printRegister(imu, BMI160::CMD);
bangclever 11:6fdec00dbb90 90 printf("\n");
bangclever 11:6fdec00dbb90 91 }
switches 8:1d48f139567d 92
switches 8:1d48f139567d 93
bangclever 11:6fdec00dbb90 94 //*****************************************************************************
bangclever 11:6fdec00dbb90 95 void printRegister(BMI160 &imu, BMI160::Registers reg)
bangclever 11:6fdec00dbb90 96 {
bangclever 11:6fdec00dbb90 97 uint8_t data;
bangclever 11:6fdec00dbb90 98 if(imu.readRegister(reg, &data) == BMI160::RTN_NO_ERROR)
bangclever 11:6fdec00dbb90 99 {
bangclever 11:6fdec00dbb90 100 printf("IMU Register 0x%02x = 0x%02x\n", reg, data);
bangclever 11:6fdec00dbb90 101 }
bangclever 11:6fdec00dbb90 102 else
bangclever 11:6fdec00dbb90 103 {
bangclever 11:6fdec00dbb90 104 printf("Failed to read register\n");
bangclever 11:6fdec00dbb90 105 }
bangclever 11:6fdec00dbb90 106 }
bangclever 11:6fdec00dbb90 107
bangclever 11:6fdec00dbb90 108
bangclever 11:6fdec00dbb90 109 //*****************************************************************************
bangclever 11:6fdec00dbb90 110 void printBlock(BMI160 &imu, BMI160::Registers startReg, BMI160::Registers stopReg)
bangclever 11:6fdec00dbb90 111 {
bangclever 11:6fdec00dbb90 112 uint8_t numBytes = ((stopReg - startReg) + 1);
bangclever 11:6fdec00dbb90 113 uint8_t buff[numBytes];
bangclever 11:6fdec00dbb90 114 uint8_t offset = static_cast<uint8_t>(startReg);
bangclever 11:6fdec00dbb90 115
bangclever 11:6fdec00dbb90 116 if(imu.readBlock(startReg, stopReg, buff) == BMI160::RTN_NO_ERROR)
bangclever 11:6fdec00dbb90 117 {
bangclever 11:6fdec00dbb90 118 for(uint8_t idx = offset; idx < (numBytes + offset); idx++)
bangclever 11:6fdec00dbb90 119 {
bangclever 11:6fdec00dbb90 120 printf("IMU Register 0x%02x = 0x%02x\n", idx, buff[idx - offset]);
bangclever 11:6fdec00dbb90 121 }
bangclever 11:6fdec00dbb90 122 }
bangclever 11:6fdec00dbb90 123 else
bangclever 11:6fdec00dbb90 124 {
bangclever 11:6fdec00dbb90 125 printf("Failed to read block\n");
bangclever 11:6fdec00dbb90 126 }
bangclever 11:6fdec00dbb90 127 }
bangclever 11:6fdec00dbb90 128
bangclever 11:6fdec00dbb90 129
switches 0:60a522ae2e35 130 int main()
switches 0:60a522ae2e35 131 {
switches 1:6923b075c8d7 132 int c;
switches 8:1d48f139567d 133 c = ' ';
switches 2:57500e991166 134
switches 2:57500e991166 135 daplink.printf("daplink serial port\r\n");
switches 3:601c11238ccb 136 microUSB.printf("micro USB serial port\r\n");
switches 2:57500e991166 137 rLED = LED_ON;
switches 2:57500e991166 138 gLED = LED_ON;
switches 2:57500e991166 139 bLED = LED_OFF;
switches 0:60a522ae2e35 140
switches 10:1f5e78dd4a7c 141
switches 10:1f5e78dd4a7c 142 Thread::wait(50); // Give the supplies time to settle before initializing the display
switches 10:1f5e78dd4a7c 143 Adafruit_SSD1306_I2c featherOLED(i2c);
bangclever 11:6fdec00dbb90 144 // featherOLED.printf("%ux%u OLED Display\r\n", featherOLED.width(), featherOLED.height());
switches 8:1d48f139567d 145 featherOLED.printf("HelloWorld \r");
switches 8:1d48f139567d 146 featherOLED.display();
bangclever 11:6fdec00dbb90 147 wait (3.0);
bangclever 11:6fdec00dbb90 148 //=====================================================
bangclever 11:6fdec00dbb90 149
bangclever 11:6fdec00dbb90 150 I2C i2cBus(P5_7, P6_0);
bangclever 11:6fdec00dbb90 151 i2cBus.frequency(400000);
bangclever 11:6fdec00dbb90 152 BMI160_I2C imu(i2cBus, BMI160_I2C::I2C_ADRS_SDO_LO);
bangclever 11:6fdec00dbb90 153
bangclever 11:6fdec00dbb90 154 uint32_t failures = 0;
bangclever 11:6fdec00dbb90 155
bangclever 11:6fdec00dbb90 156 if(imu.setSensorPowerMode(BMI160::GYRO, BMI160::NORMAL) != BMI160::RTN_NO_ERROR)
bangclever 11:6fdec00dbb90 157 {
bangclever 11:6fdec00dbb90 158 printf("Failed to set gyroscope power mode\n");
bangclever 11:6fdec00dbb90 159 failures++;
bangclever 11:6fdec00dbb90 160 }
bangclever 11:6fdec00dbb90 161 wait_ms(100);
bangclever 11:6fdec00dbb90 162
bangclever 11:6fdec00dbb90 163 if(imu.setSensorPowerMode(BMI160::ACC, BMI160::NORMAL) != BMI160::RTN_NO_ERROR)
bangclever 11:6fdec00dbb90 164 {
bangclever 11:6fdec00dbb90 165 printf("Failed to set accelerometer power mode\n");
bangclever 11:6fdec00dbb90 166 failures++;
bangclever 11:6fdec00dbb90 167 }
bangclever 11:6fdec00dbb90 168 wait_ms(100);
bangclever 11:6fdec00dbb90 169
bangclever 11:6fdec00dbb90 170
bangclever 11:6fdec00dbb90 171 BMI160::AccConfig accConfig;
bangclever 11:6fdec00dbb90 172 //example of using getSensorConfig
bangclever 11:6fdec00dbb90 173 if(imu.getSensorConfig(accConfig) == BMI160::RTN_NO_ERROR)
bangclever 11:6fdec00dbb90 174 {
bangclever 11:6fdec00dbb90 175 printf("ACC Range = %d\n", accConfig.range);
bangclever 11:6fdec00dbb90 176 printf("ACC UnderSampling = %d\n", accConfig.us);
bangclever 11:6fdec00dbb90 177 printf("ACC BandWidthParam = %d\n", accConfig.bwp);
bangclever 11:6fdec00dbb90 178 printf("ACC OutputDataRate = %d\n\n", accConfig.odr);
bangclever 11:6fdec00dbb90 179 }
bangclever 11:6fdec00dbb90 180 else
bangclever 11:6fdec00dbb90 181 {
bangclever 11:6fdec00dbb90 182 printf("Failed to get accelerometer configuration\n");
bangclever 11:6fdec00dbb90 183 failures++;
bangclever 11:6fdec00dbb90 184 }
bangclever 11:6fdec00dbb90 185
bangclever 11:6fdec00dbb90 186 //example of setting user defined configuration
bangclever 11:6fdec00dbb90 187 accConfig.range = BMI160::SENS_4G;
bangclever 11:6fdec00dbb90 188 accConfig.us = BMI160::ACC_US_OFF;
bangclever 11:6fdec00dbb90 189 accConfig.bwp = BMI160::ACC_BWP_2;
bangclever 11:6fdec00dbb90 190 accConfig.odr = BMI160::ACC_ODR_8;
bangclever 11:6fdec00dbb90 191 if(imu.setSensorConfig(accConfig) == BMI160::RTN_NO_ERROR)
bangclever 11:6fdec00dbb90 192 {
bangclever 11:6fdec00dbb90 193 // printf("ACC Range = %d\n", accConfig.range);
bangclever 11:6fdec00dbb90 194 // printf("ACC UnderSampling = %d\n", accConfig.us);
bangclever 11:6fdec00dbb90 195 // printf("ACC BandWidthParam = %d\n", accConfig.bwp);
bangclever 11:6fdec00dbb90 196 // printf("ACC OutputDataRate = %d\n\n", accConfig.odr);
bangclever 11:6fdec00dbb90 197 }
bangclever 11:6fdec00dbb90 198 else
bangclever 11:6fdec00dbb90 199 {
bangclever 11:6fdec00dbb90 200 printf("Failed to set accelerometer configuration\n");
bangclever 11:6fdec00dbb90 201 failures++;
bangclever 11:6fdec00dbb90 202 }
bangclever 11:6fdec00dbb90 203
bangclever 11:6fdec00dbb90 204 BMI160::GyroConfig gyroConfig;
bangclever 11:6fdec00dbb90 205 if(imu.getSensorConfig(gyroConfig) == BMI160::RTN_NO_ERROR)
bangclever 11:6fdec00dbb90 206 {
bangclever 11:6fdec00dbb90 207 printf("GYRO Range = %d\n", gyroConfig.range);
bangclever 11:6fdec00dbb90 208 printf("GYRO BandWidthParam = %d\n", gyroConfig.bwp);
bangclever 11:6fdec00dbb90 209 printf("GYRO OutputDataRate = %d\n\n", gyroConfig.odr);
bangclever 11:6fdec00dbb90 210 }
bangclever 11:6fdec00dbb90 211 else
bangclever 11:6fdec00dbb90 212 {
bangclever 11:6fdec00dbb90 213 printf("Failed to get gyroscope configuration\n");
bangclever 11:6fdec00dbb90 214 failures++;
bangclever 11:6fdec00dbb90 215 }
bangclever 11:6fdec00dbb90 216
bangclever 11:6fdec00dbb90 217 wait(1.0);
bangclever 11:6fdec00dbb90 218 printf("\033[H"); //home
bangclever 11:6fdec00dbb90 219 printf("\033[0J"); //erase from cursor to end of screen
bangclever 11:6fdec00dbb90 220
bangclever 11:6fdec00dbb90 221
bangclever 11:6fdec00dbb90 222 //==========================================
bangclever 11:6fdec00dbb90 223
bangclever 11:6fdec00dbb90 224 if(imu.setSensorPowerMode(BMI160::GYRO, BMI160::NORMAL) != BMI160::RTN_NO_ERROR)
bangclever 11:6fdec00dbb90 225 {
bangclever 11:6fdec00dbb90 226 printf("Failed to set gyroscope power mode\n");
bangclever 11:6fdec00dbb90 227 failures++;
bangclever 11:6fdec00dbb90 228 }
bangclever 11:6fdec00dbb90 229 wait_ms(100);
bangclever 11:6fdec00dbb90 230
bangclever 11:6fdec00dbb90 231 if(imu.setSensorPowerMode(BMI160::ACC, BMI160::NORMAL) != BMI160::RTN_NO_ERROR)
bangclever 11:6fdec00dbb90 232 {
bangclever 11:6fdec00dbb90 233 printf("Failed to set accelerometer power mode\n");
bangclever 11:6fdec00dbb90 234 failures++;
bangclever 11:6fdec00dbb90 235 }
bangclever 11:6fdec00dbb90 236 wait_ms(100);
bangclever 11:6fdec00dbb90 237
switches 1:6923b075c8d7 238
switches 1:6923b075c8d7 239 while(1) {
switches 8:1d48f139567d 240 Thread::wait(250);
switches 8:1d48f139567d 241 if (microUSB.readable()) {
switches 8:1d48f139567d 242 c = microUSB.getc();
switches 8:1d48f139567d 243 microUSB.putc(c);
switches 8:1d48f139567d 244 daplink.putc(c);
switches 8:1d48f139567d 245 }
switches 8:1d48f139567d 246 if (daplink.readable()) {
switches 8:1d48f139567d 247 c = daplink.getc();
switches 8:1d48f139567d 248 microUSB.putc(c);
switches 8:1d48f139567d 249 daplink.putc(c);
switches 8:1d48f139567d 250 }
bangclever 11:6fdec00dbb90 251
bangclever 11:6fdec00dbb90 252 int high =1;
bangclever 11:6fdec00dbb90 253 int low =0;
bangclever 11:6fdec00dbb90 254 DigitalOut trigger (P5_2);
bangclever 11:6fdec00dbb90 255 trigger = high;
bangclever 11:6fdec00dbb90 256 wait_us(10);
bangclever 11:6fdec00dbb90 257 trigger = low;
bangclever 11:6fdec00dbb90 258
bangclever 11:6fdec00dbb90 259 DigitalIn echo (P5_1);
bangclever 11:6fdec00dbb90 260 if ( echo == high )
bangclever 11:6fdec00dbb90 261 {
bangclever 11:6fdec00dbb90 262
bangclever 11:6fdec00dbb90 263 gLED = LED_ON;
bangclever 11:6fdec00dbb90 264 wait(5);
bangclever 11:6fdec00dbb90 265 gLED = LED_OFF;
bangclever 11:6fdec00dbb90 266
bangclever 11:6fdec00dbb90 267 }
bangclever 11:6fdec00dbb90 268
bangclever 11:6fdec00dbb90 269
bangclever 11:6fdec00dbb90 270 //if (echo == 1)
bangclever 11:6fdec00dbb90 271 //{
bangclever 11:6fdec00dbb90 272 // DigitalOut gLED(LED2, LED_ON);
bangclever 11:6fdec00dbb90 273 // wait(1);
bangclever 11:6fdec00dbb90 274 //gLED = LED_OFF;
bangclever 11:6fdec00dbb90 275 // }
bangclever 11:6fdec00dbb90 276
bangclever 11:6fdec00dbb90 277 //*************************testing timeer *******************************************
bangclever 11:6fdec00dbb90 278 /*
bangclever 11:6fdec00dbb90 279 t.start();
bangclever 11:6fdec00dbb90 280 printf("Hello World!\n");
bangclever 11:6fdec00dbb90 281 t.stop();
bangclever 11:6fdec00dbb90 282 printf("The time taken was %f seconds\n", t.read());
bangclever 11:6fdec00dbb90 283
bangclever 11:6fdec00dbb90 284 */
bangclever 11:6fdec00dbb90 285
bangclever 11:6fdec00dbb90 286 // **********************************************************************************
bangclever 11:6fdec00dbb90 287
bangclever 11:6fdec00dbb90 288
bangclever 11:6fdec00dbb90 289
bangclever 11:6fdec00dbb90 290
bangclever 11:6fdec00dbb90 291 float imuTemperature;
bangclever 11:6fdec00dbb90 292 BMI160::SensorData accData;
bangclever 11:6fdec00dbb90 293 BMI160::SensorData gyroData;
bangclever 11:6fdec00dbb90 294 BMI160::SensorTime sensorTime;
bangclever 11:6fdec00dbb90 295
bangclever 11:6fdec00dbb90 296 imu.getGyroAccXYZandSensorTime(accData, gyroData, sensorTime, accConfig.range, gyroConfig.range);
bangclever 11:6fdec00dbb90 297 imu.getTemperature(&imuTemperature);
bangclever 11:6fdec00dbb90 298
bangclever 11:6fdec00dbb90 299
switches 9:ecdad18f61c2 300 rLED = aButton;
switches 9:ecdad18f61c2 301 gLED = bButton;
switches 9:ecdad18f61c2 302 bLED = cButton;
switches 8:1d48f139567d 303 featherOLED.clearDisplay();
switches 8:1d48f139567d 304 featherOLED.setTextCursor(0,0);
bangclever 11:6fdec00dbb90 305 featherOLED.printf("SensorTemp = %s%5.3f\n", "\033", imuTemperature);
bangclever 11:6fdec00dbb90 306 featherOLED.printf("X%s%4.1f ", "\033", gyroData.xAxis.scaled);
bangclever 11:6fdec00dbb90 307 featherOLED.printf("Y%s%4.1f ", "\033", gyroData.yAxis.scaled);
bangclever 11:6fdec00dbb90 308 featherOLED.printf("Z%s%4.1f\n", "\033", gyroData.zAxis.scaled);
bangclever 11:6fdec00dbb90 309 //printf("GYRO yAxis = %s%5.1f\n", "\033[K", gyroData.yAxis.scaled);
bangclever 11:6fdec00dbb90 310 // printf("GYRO zAxis = %s%5.1f\n", "\033[K", gyroData.zAxis.scaled);
bangclever 11:6fdec00dbb90 311 //featherOLED.printf("MAX32630FTHR OLED\n");
switches 9:ecdad18f61c2 312 featherOLED.printf("AIN0/1: %1.2f, %1.2f\n", (6.0f * ain0), (6.0f * ain1) ); // analog inputs 0,1
bangclever 11:6fdec00dbb90 313 // featherOLED.printf("AIN2/3: %1.2f, %1.2f\n", (1.2f * ain2), (1.2f * ain3) ); // analog inputs 2,3
bangclever 11:6fdec00dbb90 314 // featherOLED.printf("UART:%c A:%d B:%d C:%d\n", c, aButton.read(), bButton.read(), cButton.read()); // UART and Buttons
switches 8:1d48f139567d 315 featherOLED.display();
switches 8:1d48f139567d 316
switches 0:60a522ae2e35 317 }
switches 0:60a522ae2e35 318 }
switches 0:60a522ae2e35 319