This is as far as I got, then I had to refocus my life for a bit.

it acts as two independent i2c slaves on the same address (two separate buses). The idea is to take the place of the two capacitive touch-sensors in the MiLight remote, and pretend to be them, and get the microcontroller on the little RF header board in the remote to send out the commands we want. This should overcome the need to understand the new RGB+DualWhite (RGB+CCT) MiLight protocol with its as yet unbroken encryption.

This code is terrible and it will only spit out the same packet, but it’s a start. I was able to unpredictably get the bulb to change from off to on or flashing or blue.

I used a Feather M0, the ARMĀ one, which can run two i2c buses at the same time via its sercom thing.

I think I left some of the code commented out for the second i2c bus, before I went to sleep.. i was just experimenting. you can uncomment it, it was working.

// Wire Slave Sender
// by Nicholas Zambetti <http://www.zambetti.com>

// Demonstrates use of the Wire library
// Sends data as an I2C/TWI slave device
// Refer to the “Wire Master Reader” example for use with this

// Created 29 March 2006

// This example code is in the public domain.
#include <Wire.h>
#include “wiring_private.h” // pinPeripheral() function

TwoWire myWire(&sercom1, 13, 11); // first pin is SDA, second pin is SCL

int reqNo_ch1 = 0;
int reqNo_ch2 = 0;
int on = 0;

char val1;
char val2;
char ch1read;
char ch2read;
char ch1write;
char ch2write;

byte data1[5];
byte data2[5];
byte cmdon[] = {0x02, 0x00, 0x01, 0x00, 0x00};
byte cmdoff[] = {0x02, 0x00, 0x02, 0x00, 0x00};
byte btnReleased[] = {0x02, 0x00, 0x00, 0x00, 0x00};

void setup() {
Wire.begin(0x53); // join first i2c bus with address 0x53
Wire.onRequest(requestEvent1); // register event for i2c bus 1
Wire.onReceive(receiveEvent1); // register receive event (for Writes from master) for i2c bus 1
myWire.begin(0x53); // join second i2c bus with address 0x53
pinPeripheral(11, PIO_SERCOM);
pinPeripheral(13, PIO_SERCOM); // Assign pins 13 & 11 to SERCOM functionality
myWire.onRequest(requestEvent2); // register event for i2c bus 2
myWire.onReceive(receiveEvent2); // register receive event (for Writes from master) for i2c bus 2
// while (!Serial);
Serial.begin(115200); // start serial for output

}

void loop() {
if (ch1read == 1) {
if (on == 1) Serial.print(“R1 on “);
if (on == 0) Serial.print(“R1 off “);
ch1read = 0;
}
if (ch1write == 1) {
Serial.print(“W1:”);
PrintHex83(data1, 5);
ch1write = 0;
}

if (ch2read == 1) {
Serial.print(“R2”);
ch2read = 0;
}
if (ch2write == 1) {
Serial.print(“W2:”);
PrintHex83(data2, 5);
ch2write = 0;
}

}
// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent1() {
ch1read = 1;
if (reqNo_ch1 >1) {
if (on == 0) {
Wire.write(cmdon, 5); // respond with “on”
on = 1;
//reqNo_ch1 = ;
}
else {
Wire.write(cmdoff, 5); // respond with “off”
on = 0;
//reqNo_ch1 = 0;
}
reqNo_ch1–;
}
else {
Wire.write(btnReleased, 5); // respond with “button released”
reqNo_ch1 = 5;
}
}

void receiveEvent1(int howMany)
{
ch1write = 1;
int x = 1;
while (Wire.available())
{
data1[x] = Wire.read(); // receive byte as a character
x++;
}
}

void requestEvent2() {
ch2read = 1;
// if (reqNo_ch2 >1) {
// if (on == 0) {
// myWire.write(cmdon, 5); // respond with “on”
// on = 1;
// reqNo_ch2 = 0;
// }
// else {
// myWire.write(cmdoff, 5); // respond with “off”
// on = 0;
// }
// reqNo_ch2–;
// }
// else {
myWire.write(btnReleased, 5); // respond with “button released”
// reqNo_ch2 = 5;
// }
}

void receiveEvent2(int howMany)
{
ch2write = 1;
int x=1;
while (myWire.available())
{
data2[x] = myWire.read(); // receive byte as a character
x++;
}
}

extern “C” {
void SERCOM1_Handler(void) {
myWire.onService();
}
}

void PrintHex83(uint8_t *data, uint8_t length) // prints 8-bit data in hex
{
char tmp[length*2+1];
byte first ;
int j=0;
for (uint8_t i=0; i<length; i++)
{
first = (data[i] >> 4) | 48;
if (first > 57) tmp[j] = first + (byte)39;
else tmp[j] = first ;
j++;

first = (data[i] & 0x0F) | 48;
if (first > 57) tmp[j] = first + (byte)39;
else tmp[j] = first;
j++;
}
tmp[length*2] = 0;
Serial.println(tmp);
}