I'm doing a project that will use two TOF10120 laser sensors to measure different distances using the arduino uno but the values are the same - sensors

'The issue im having is that I can't get the right laser to stop reading data and start reading data from the left laser. I just get the same value no matter which laser i move. i tried connnecting them to two digital pins to switch between which one will be read but it's not working properly.
i also tried using different analog pins but it doesn't work. i think the problem there is that the SDA and SCL pin is A5 and A4. that is why i decided to try using two digital pins to switch which laser gets data sent to SDA.
/* This code is to use with ToF10120 Laser Range Sensor to measure distance in (mm)and (inches) and shows it
type here
on the Serial monitor and also on the I2C LCD using I²c inteface
Modified and adapted from a code found on some dodgy chinese website
Refer to https://www.electroniclinic.com/ for more details
*/
/*#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <SimpleTimer.h>
int Red=12;
int Green=10;
int Yellow=7;
//#define sensorScl A1
//#define sensorSda A0
//int addy=0x150;
int pinR=2;
int pinL=4;
SimpleTimer timer;
unsigned char ok_flag;
unsigned char fail_flag;
unsigned short lenth_val = 0;
unsigned char i2c_rx_buf[16];
unsigned char dirsend_flag=0;
int x_mm; // distance in millimeters
float y_inches; // distance in inches
for the OLED display
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
int relay = 13;
int relay_flag = 0;
const unsigned char epd_bitmap_ULL [] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc4, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x84, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x88, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x08, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x08, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x18, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x18, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x01, 0xff, 0x00, 0x07, 0xff, 0xfe, 0x10, 0x01, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff,
0x00, 0x01, 0xff, 0x00, 0x07, 0xff, 0xfe, 0x30, 0x00, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff,
0x00, 0x01, 0xff, 0x00, 0x07, 0xff, 0xfe, 0x30, 0x00, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xf0, 0x3f, 0xff, 0xfe, 0x30, 0x00, 0xff, 0xff, 0xe0, 0x1f, 0xff, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xf8, 0x3f, 0xff, 0xfc, 0x30, 0x00, 0x7f, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xf8, 0x3f, 0x80, 0x3c, 0x60, 0x00, 0x7c, 0x03, 0xf0, 0x1f, 0xff, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xf8, 0x3e, 0x00, 0x1c, 0x60, 0x00, 0x70, 0x01, 0xf0, 0x1f, 0xff, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xf8, 0x3c, 0x7f, 0x04, 0x60, 0x00, 0x03, 0xf0, 0x70, 0x1f, 0xff, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xf8, 0x38, 0xff, 0xc0, 0x60, 0x00, 0x0f, 0xf8, 0x30, 0x1f, 0xff, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xf8, 0x71, 0xc0, 0x60, 0x60, 0x00, 0x1e, 0x00, 0x30, 0x1f, 0xff, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xf8, 0x73, 0x80, 0x10, 0x60, 0x00, 0x38, 0x00, 0x10, 0x1f, 0xff, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xf8, 0x67, 0x00, 0x00, 0x70, 0x00, 0x70, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xf8, 0x66, 0x00, 0x00, 0x30, 0x00, 0xe0, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xf8, 0x46, 0x00, 0x00, 0x38, 0x00, 0xc0, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xf8, 0x4c, 0x00, 0x00, 0x18, 0x01, 0x80, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xf8, 0x4c, 0x00, 0x00, 0x18, 0x03, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xf8, 0x4c, 0x00, 0x00, 0x08, 0x03, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xf8, 0x4c, 0x03, 0x80, 0x0c, 0x06, 0x07, 0x80, 0x00, 0x3f, 0xff, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xf8, 0x64, 0x1f, 0xf0, 0x0c, 0x06, 0x1f, 0xe0, 0x00, 0x3f, 0xff, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xf8, 0x64, 0x1f, 0xf8, 0x04, 0x0c, 0x3f, 0xf0, 0x00, 0x1f, 0xff, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xf8, 0x74, 0x3f, 0xf8, 0x00, 0x04, 0x7f, 0xf0, 0x10, 0x3f, 0xff, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xf8, 0x70, 0x3f, 0xfc, 0x1f, 0xe0, 0x7f, 0xf8, 0x10, 0x3f, 0xff, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xf8, 0x78, 0x3f, 0xf8, 0x7f, 0xf0, 0x3f, 0xf8, 0x30, 0x3f, 0xff, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xf8, 0x7c, 0x3e, 0xf8, 0x00, 0x00, 0x3e, 0xf8, 0x70, 0x1f, 0xff, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xf8, 0x7e, 0x38, 0xf8, 0x00, 0x00, 0x3e, 0x78, 0xf0, 0x3f, 0xff, 0xff, 0xff,
0xf0, 0x1f, 0xff, 0xf8, 0x7f, 0xf0, 0xf8, 0x00, 0x00, 0x3e, 0x3b, 0xf0, 0x3f, 0xff, 0xc7, 0xff,
0xf0, 0x1f, 0xff, 0xf0, 0x7f, 0xf0, 0x70, 0x00, 0x00, 0x10, 0x1f, 0xf0, 0x3f, 0xff, 0x87, 0xff,
0xf0, 0x1f, 0xff, 0xf0, 0xff, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x1f, 0xf0, 0x3f, 0xff, 0x87, 0xff,
0xf8, 0x0f, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00, 0xc0, 0x00, 0x0f, 0xf0, 0x3f, 0xff, 0x8f, 0xff,
0xf8, 0x07, 0xff, 0xc0, 0xff, 0xe0, 0x00, 0x00, 0xc0, 0x00, 0x0f, 0xf0, 0x3f, 0xff, 0x8f, 0xff,
0xfc, 0x03, 0xff, 0x01, 0xff, 0xe0, 0x00, 0x00, 0xc0, 0x00, 0x0f, 0xf0, 0x3f, 0xff, 0x0f, 0xff,
0xfc, 0x00, 0x30, 0x03, 0xff, 0xe0, 0x00, 0x00, 0x60, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x0f, 0xff,
0xfe, 0x00, 0x00, 0x07, 0xff, 0xe0, 0x00, 0x00, 0x60, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x0f, 0xff,
0xff, 0x00, 0x00, 0x0f, 0xff, 0xf0, 0x00, 0x00, 0x60, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x0f, 0xff,
0xff, 0x80, 0x00, 0x1f, 0xff, 0xf0, 0x00, 0x00, 0x30, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x0f, 0xff,
0xff, 0xe0, 0x00, 0x7f, 0xff, 0xf8, 0x00, 0x00, 0x30, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x1f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x31, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x31, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x31, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = 1040)
const int epd_bitmap_allArray_LEN = 1;
const unsigned char* epd_bitmap_allArray[1] = {
epd_bitmap_ULL
};
void setup() {
Wire.begin();
Serial.begin(9600,SERIAL_8N1);
pinMode(relay, OUTPUT);
digitalWrite(relay, LOW);
printf_begin();
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextColor(WHITE);
pinMode(Red, OUTPUT);
display.drawBitmap(0,0,epd_bitmap_ULL,128,64,WHITE);
display.display();
delay(500);
display.clearDisplay();
timer.setInterval(500L, display_measurement);
void loop() {
timer.run(); // Initiates SimpleTimer
x_mm = ReadDistance();
Serial.print(x_mm);
Serial.println(" mm");
You can convert millimeters to inches in one of two ways: divide the number of millimeters by 25.4, or multiply the number of millimeters by 0.0394
y_inches = x_mm * 0.00328084;
Serial.print(y_inches);
Serial.println(" Ft");
if( (y_inches > 10 ) && (relay_flag == 0))
{
digitalWrite(relay, LOW);
relay_flag = 1;
}
if( (y_inches <= 5 ) && (relay_flag == 1))
{
digitalWrite(relay, HIGH);
relay_flag = 0;
}
}
int serial_putc( char c, struct __file * )
{
Serial.write( c );
return c;
}
void printf_begin(void)
{
fdevopen( &serial_putc, 0 );
}
void SensorRead(unsigned char addr,unsigned char* datbuf,unsigned char cnt)
{
pinL=HIGH;
pinR=LOW;
unsigned short result=0;
step 1: instruct sensor to read echoes
Wire.beginTransmission(82); // transmit to device #82 (0x52), you can also find this address using the i2c_scanner code, which is available on electroniclinic.com
the address specified in the datasheet is 164 (0xa4)
but i2c adressing uses the high 7 bits so it's 82
Wire.write(byte(addr)); // sets distance data address (addr)
Wire.endTransmission(); // stop transmitting
step 2: wait for readings to happen
delay(1); // datasheet suggests at least 30uS
step 3: request reading from sensor
Wire.requestFrom(82, cnt); // request cnt bytes from slave device #82 (0x52)
step 5: receive reading from sensor
if (cnt <= Wire.available()) { // if two bytes were received
*datbuf++ = Wire.read(); // receive high byte (overwrites previous reading)
*datbuf++ = Wire.read(); // receive low byte as lower 8 bits
}
}
int ReadDistance(){
SensorRead(0x00,i2c_rx_buf,2);
lenth_val=i2c_rx_buf[0];
lenth_val=lenth_val<<8;
lenth_val|=i2c_rx_buf[1];
delay(300);
return lenth_val;
}
void display_measurement()
{
display on Oled display
Oled display
if((lenth_val*0.00328084)<=2.5&&lenth_val>=0){
digitalWrite(Red, HIGH);
digitalWrite(Green, LOW);
digitalWrite(Yellow, LOW);
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0,0); // column row
display.println("Warning!");
display.println();
display.print(" RED");
display.println();
display.setTextSize(1);
display.setCursor(55, 0);
display.setTextSize(1);
display.setCursor(0,30);
display.print("ft:");
display.setTextSize(1);
display.setCursor(20,30);
display.print(y_inches);
display.setCursor(55, 90);
display.setTextSize(1);
display.setCursor(0,50);
display.print("LEFT SIDE");
display.setCursor(55, 90);
display.display();
}else if((lenth_val0.00328084)<=3.7&&(lenth_val0.00328084)>=2.6){
digitalWrite(Yellow, HIGH);
digitalWrite(Red, LOW);
digitalWrite(Green, LOW);
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0,0); // column row
display.println("CAUTION");
display.println();
display.print(" Yellow");
display.println();
display.setTextSize(1);
display.setCursor(55, 0);
display.setTextSize(1);
display.setCursor(0,30);
display.print("ft:");
display.setTextSize(1);
display.setCursor(20,30);
display.print(y_inches);
display.setCursor(55, 90);
display.setTextSize(1);
display.setCursor(0,50);
display.print("LEFT SIDE");
display.setCursor(55, 90);
display.display();
}else if((lenth_val*0.00328084)>3.7){
digitalWrite(Green, HIGH);
digitalWrite(Red, LOW);
digitalWrite(Yellow, LOW);
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0,0); // column row
display.println("-->Safe<--");
display.println();
display.print(" Green");
display.println();
display.setTextSize(1);
display.setCursor(55, 0);
display.setTextSize(1);
display.setCursor(0,30);
display.print("ft:");
display.setTextSize(1);
display.setCursor(20,30);
display.print(y_inches);
display.setCursor(55, 90);
display.setTextSize(1);
display.setCursor(0,50);
display.print("LEFT SIDE");
display.setCursor(55, 90);
display.display();
}
delay(3000);
}
void SensorRead2(unsigned char addy,unsigned char* datbuf,unsigned char sensorScl)
{
pinR=HIGH;
pinL=LOW;
unsigned short result=0;
step 1: instruct sensor to read echoes
Wire.beginTransmission(82); // transmit to device #82 (0x52), you can also find this address using the i2c_scanner code, which is available on electroniclinic.com
the address specified in the datasheet is 164 (0xa4)
but i2c adressing uses the high 7 bits so it's 82
Wire.write(byte(addy)); // sets distance data address (addr)
Wire.endTransmission(); // stop transmitting
step 2: wait for readings to happen
delay(1); // datasheet suggests at least 30uS
step 3: request reading from sensor
Wire.requestFrom(82, sensorScl); // request cnt bytes from slave device #82 (0x52)
step 5: receive reading from sensor
if (sensorScl <= Wire.available()) { // if two bytes were received
*datbuf++ = Wire.read(); // receive high byte (overwrites previous reading)
*datbuf++ = Wire.read(); // receive low byte as lower 8 bits
}
}
int ReadDistance2(){
SensorRead(0x00,i2c_rx_buf,2);
lenth_val=i2c_rx_buf[0];
lenth_val=lenth_val<<8;
lenth_val|=i2c_rx_buf[1];
delay(300);
return lenth_val;
}
void display_measurement2()
{
display on Oled display
Oled display
if((lenth_val*0.00328084)<=2.5&&lenth_val>=0){
digitalWrite(Red, HIGH);
digitalWrite(Green, LOW);
digitalWrite(Yellow, LOW);
display.clearDisplay();
display.setTextSize(1);
display.setCursor(40,40); // column row
display.println("Warning!");
display.println();
display.print(" RED");
display.println();
display.setTextSize(1);
display.setCursor(90, 0);
display.setTextSize(1);
display.setCursor(40,60);
display.print("ft:");
display.setTextSize(1);
display.setCursor(20,30);
display.print(y_inches);
display.setCursor(55, 90);
display.setTextSize(1);
display.setCursor(0,50);
display.print("LEFT SIDE");
display.setCursor(55, 90);
display.display();
}else if((lenth_val0.00328084)<=3.7&&(lenth_val0.00328084)>=2.6){
digitalWrite(Yellow, HIGH);
digitalWrite(Red, LOW);
digitalWrite(Green, LOW);
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0,0); // column row
display.println("CAUTION");
display.println();
display.print(" Yellow");
display.println();
display.setTextSize(1);
display.setCursor(55, 0);
display.setTextSize(1);
display.setCursor(0,30);
display.print("ft:");
display.setTextSize(1);
display.setCursor(20,30);
display.print(y_inches);
display.setCursor(55, 90);
display.setTextSize(1);
display.setCursor(0,50);
display.print("LEFT SIDE");
display.setCursor(55, 90);
display.display();
}else if((lenth_val*0.00328084)>3.7){
digitalWrite(Green, HIGH);
digitalWrite(Red, LOW);
digitalWrite(Yellow, LOW);
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0,0); // column row
display.println("-->Safe<--");
display.println();
display.print(" Green");
display.println();
display.setTextSize(1);
display.setCursor(55, 0);
display.setTextSize(1);
display.setCursor(0,30);
display.print("ft:");
display.setTextSize(1);
display.setCursor(20,30);
display.print(y_inches);
display.setCursor(55, 90);
display.setTextSize(1);
display.setCursor(0,50);
display.print("LEFT SIDE");
display.setCursor(55, 90);
display.display();
}

Related

How to manipulate buffer in Rust?

a few weeks ago I got interested in Rust. So far I have only read online tutorials and wonder how to manipulate buffer memory in Rust. Let's say I have C code like this:
int main()
{
char buffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa };
int a = *(int*)&buffer[0];
a = 0xdeadc0de;
short b = *(short*)&buffer[4];
b = 0xbadf;
*(int*)&buffer[0] = a;
*(short*)&buffer[4] = b;
//buffer memory: de c0 ad de df ba 77 88 99 aa
return 0;
}
Could anyone write this in Rust please? I think there's no casting in Rust, right?
Direct buffer manipulation through transmuted references is considered unsafe in Rust. You can of course use the unsafe keyword for writing into memory directly, but that would negate the whole safety advantage of using Rust.
You can create an u32, convert it to a [u8] array and then write that into the buffer. But you cannot safely get a &u32 reference from a buffer.
fn main() {
let mut buffer = vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa];
let a: u32 = 0xdeadc0de;
let a_bytes = a.to_le_bytes();
buffer[0..4].copy_from_slice(&a_bytes);
let b: u16 = 0xbadf;
let b_bytes = b.to_le_bytes();
buffer[4..6].copy_from_slice(&b_bytes);
println!("{:x?}", buffer);
}
[de, c0, ad, de, df, ba, 77, 88, 99, aa]
Just for reference, this is how this would look like with unsafe code.
I highly discourage this solution, though.
fn main() {
let mut buffer: Vec<u8> = vec![0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa];
unsafe {
let ptr = buffer.as_mut_ptr();
let a = ptr.offset(0) as *mut u32;
*a = 0xdeadc0de;
let b = ptr.offset(4) as *mut u16;
*b = 0xbadf;
}
println!("{:x?}", buffer);
}
[de, c0, ad, de, df, ba, 77, 88, 99, aa]
Note that the unsafe solution does not behave exactly like the safe solution. It will flip the bytes if compiled on a big-endian architecture.
This is what to_le_bytes prevents.

Java enum-like behavior in Rust

I want to have an enum where each value in the enum stores a constant array of bytes that represent the RGBA values for a color. In Java I would do this:
public enum Color {
BLACK([0x0C, 0x00, 0x05, 0xFF]),
BLUE([0x00, 0x2D, 0xFF, 0xFF]),
RED([0xFF, 0x3E, 0x00, 0xFF]);
private final byte[] rgba;
Color(byte[] rgba) {
this.rgba = rgba;
}
public int[] value() {
return rgba;
}
}
Then I could pass around Color types and just use color.value() to get the bytes out. This is what I have in Rust:
struct Color;
impl Color {
pub const BLACK: [u8; 4] = [0x0C, 0x00, 0x05, 0xFF];
pub const BLUE: [u8; 4] = [0x00, 0x2D, 0xFF, 0xFF];
pub const RED: [u8; 4] = [0xFF, 0x3E, 0x00, 0xFF];
}
But this means that anywhere I want to pass a Color the type is [u8; 4]. I could call the struct Colors and then do pub type Color = [u8; 4]. Then you could have the type as Color but then it would be Colors::BLACK which seems weird.
If you want to have a strong type for the byte array in the Color struct, you can use the following notation, called a tuple struct:
struct Color([u8; 4]);
impl Color {
pub const BLACK: Color = Color([0x0C, 0x00, 0x05, 0xFF]);
pub const BLUE: Color = Color([0x00, 0x2D, 0xFF, 0xFF]);
pub const RED: Color = Color([0xFF, 0x3E, 0x00, 0xFF]);
}
fn main() {
// classic way of accessing data
println!("{:?}", Color::BLACK.0);
// using destructuring
let Color(bytes) = Color::BLUE;
println!("{:?}", bytes);
}
Playground link
I have created a crate enumeration just for this.
Example using my crate:
use enumeration::prelude::*;
enumerate!(pub Color(u8; [u8; 4])
Black = [0x0C, 0x00, 0x05, 0xFF]
Blue = [0x00, 0x2D, 0xFF, 0xFF]
Red = [0xFF, 0x3E, 0x00, 0xFF]
);
pub fn main() {
assert_eq!(*Color::Black.value(), [0x0C, 0x00, 0x05, 0xFF]);
assert_eq!(*Color::Blue.value(), [0x00, 0x2D, 0xFF, 0xFF]);
assert_eq!(*Color::Red.value(), [0xFF, 0x3E, 0x00, 0xFF]);
}

How to execute raw instructions from a memory buffer in Rust?

I'm attempting to make a buffer of memory executable, then execute it in Rust. I've gotten all the way until I need to cast the raw executable bytes as code/instructions. You can see a working example in C below.
Extra details:
Rust 1.34
Linux
CC 8.2.1
unsigned char code[] = {
0x55, // push %rbp
0x48, 0x89, 0xe5, // mov %rsp,%rbp
0xb8, 0x37, 0x00, 0x00, 0x00, // mov $0x37,%eax
0xc9, // leaveq
0xc3 // retq
};
void reflect(const unsigned char *code) {
void *buf;
/* copy code to executable buffer */
buf = mmap(0, sizeof(code), PROT_READ|PROT_WRITE|PROT_EXEC,MAP_PRIVATE|MAP_ANON,-1,0);
memcpy(buf, code, sizeof(code));
((void (*) (void))buf)();
}
extern crate mmap;
use mmap::{MapOption, MemoryMap};
unsafe fn reflect(instructions: &[u8]) {
let map = MemoryMap::new(
instructions.len(),
&[
MapOption::MapAddr(0 as *mut u8),
MapOption::MapOffset(0),
MapOption::MapFd(-1),
MapOption::MapReadable,
MapOption::MapWritable,
MapOption::MapExecutable,
MapOption::MapNonStandardFlags(libc::MAP_ANON),
MapOption::MapNonStandardFlags(libc::MAP_PRIVATE),
],
)
.unwrap();
std::ptr::copy(instructions.as_ptr(), map.data(), instructions.len());
// How to cast into extern "C" fn() ?
}
Use mem::transmute to cast a raw pointer to a function pointer type.
use std::mem;
let func: unsafe extern "C" fn() = mem::transmute(map.data());
func();

How to implement bitwise operations on a bitflags enum?

I have an enum that looks like this:
#[repr(u8)]
pub enum PublicFlags {
PublicFlagVersion = 0x01,
PublicFlagReset = 0x02,
NoncePresent = 0x04,
IdPresent = 0x08,
PktNumLen4 = 0x30,
PktNumLen2 = 0x20,
PktNumLen1 = 0x10,
Multipath = 0x40,
}
I want to do a bitwise operation on several of the enum values. However, the Rust compiler complains:
an implementation of `std::ops::BitAnd` might be missing for `PublicFlags`.
An enum in Rust is not intended to be used as bit flags. PublicFlags can only take the values given in the enum (and not a combination). So for instance, the following match statement is exhaustive:
let flags: PublicFlags;
...
match flags {
PublicFlagVersion => {...}
PublicFlagReset => {...}
NoncePresent => {...}
IdPresent => {...}
PktNumLen4 => {...}
PktNumLen2 => {...}
PktNumLen1 => {...}
Multipath => {...}
}
There is no way to have a PublicFlags variable with a combination of the flags.
The solution is to actually store the value as a u8, then use constants to store the value of each flag. This can be cumbersome, but thankfully the bitflags crate wraps all the boilerplate up in a macro for you. Here is an example how you would create your struct using bitflags:
#[macro_use]
extern crate bitflags;
bitflags! {
flags PublicFlags: u8 {
const PUBLIC_FLAG_VERSION = 0x01,
const PUBLIC_FLAG_RESET = 0x02,
const NONCE_PRESENT = 0x04,
const ID_PRESENT = 0x08,
const PKT_NUM_LEN_4 = 0x30,
const PKT_NUM_LEN_2 = 0x20,
const PKT_NUM_LEN_1 = 0x10,
const MULTIPATH = 0x40,
}
}
fn main() {
let flag = PUBLIC_FLAG_VERSION | ID_PRESENT;
assert!((flag & MULTIPATH).is_empty());
assert!(flag.contains(ID_PRESENT));
}
This could work as an alternative answer without new dependencies.
pub mod PublicFlags {
pub const PublicFlagVersion: u8 = 0x01;
pub const PublicFlagReset: u8 = 0x02;
pub const NoncePresent: u8 = 0x04;
pub const IdPresent: u8 = 0x08;
pub const PktNumLen4: u8 = 0x30;
pub const PktNumLen2: u8 = 0x20;
pub const PktNumLen1: u8 = 0x10;
pub const Multipath: u8 = 0x40;
}
You can refer to the values just like with an enum with PublicFlags::PublicFlagVersion, or add use PublicFlags::*; if it is cleaner to reference the values without specifying the namespace.

Interfacing with structs and anonymous unions with c2hs

How would one go about encoding this chunk of C code in a .chs file so that c2hs can transform it to something relatively nice?
typedef enum {
MONOME_BUTTON_UP = 0x00,
MONOME_BUTTON_DOWN = 0x01,
MONOME_ENCODER_DELTA = 0x02,
MONOME_ENCODER_KEY_UP = 0x03,
MONOME_ENCODER_KEY_DOWN = 0x04,
MONOME_TILT = 0x05,
/* update this if you add event types */
MONOME_EVENT_MAX = 0x06
} monome_event_type_t;
typedef struct monome monome_t; /* opaque data type */
typedef struct monome_event monome_event_t;
typedef void (*monome_event_callback_t)
(const monome_event_t *event, void *data);
struct monome_event {
monome_t *monome;
monome_event_type_t event_type;
/* __extension__ for anonymous unions in gcc */
__extension__ union {
struct {
unsigned int x;
unsigned int y;
} grid;
struct {
unsigned int number;
int delta;
} encoder;
struct {
unsigned int sensor;
int x;
int y;
int z;
} tilt;
};
};
How about this: change the code so that you name the members. The layout in memory is the same so that it will be binary compatible. You would have to do this patch for each version of the lib.
struct monome_event {
monome_t *monome;
monome_event_type_t event_type;
/* __extension__ for anonymous unions in gcc */
__extension__ union {
struct me_grid {
unsigned int x;
unsigned int y;
} grid;
struct me_encoder {
unsigned int number;
int delta;
} encoder;
struct me_tilt {
unsigned int sensor;
int x;
int y;
int z;
} tilt;
};
};

Resources