temperature stuff actually working now

This commit is contained in:
Triss 2021-06-21 17:55:06 +02:00
parent 9f3802627a
commit d5484cf38f
7 changed files with 150 additions and 11 deletions

View File

@ -138,12 +138,19 @@ sensor (the exact sensor emulated is the Microchip MCP9808). To have it show
up in `sensors`, do the following (with `BUSNUM` the number from the above
`i2cdetect -l` output):
```
$ ./dmctl.py /dev/ttyACM1 --i2ctemp 0x18 # need to give it an address first
$ sudo modprobe jc42
$ # now tell the jc42 module that the device can be found at this address
$ echo "jc42 0x18" | sudo tee /sys/bus/i2c/device/i2c-BUSNUM/new_device
$ sudo sensors
$ sudo sensors # it should show up now:
jc42-i2c-BUSNUM-18
Adapter: i2c-tiny-usb at bus 001 device 032
temp1: +23.1°C (low = -20.0°C)
(high = +75.0°C, hyst = +75.0°C)
(crit = +80.0°C, hyst = +80.0°C)
```
Temperature readout is currently not really working.
Temperature readout may be a bit higher than the ambient temperature.
### Runtime configuration
@ -156,6 +163,7 @@ The currently implemented options are:
- `i2ctemp`: Get or set the I2C address of the fake I2C device of the temperature
sensor. Use 0 for getting the value, 0xff for disabling, and any
other for setting the address. The I2C device emulated is an MCP9808.
When setting a value, the old value is printed.
```
usage: dmctl [-h] [-v] [--ctsrts [CTSRTS]] tty
@ -201,7 +209,7 @@ libco is licensed under the [ISC license](https://opensource.org/licenses/ISC)
to use the UART interface as a loopback thing.
- [ ] Second UART port for when stdio UART is disabled?
- [x] I2C support by emulating the I2C Tiny USB
- [ ] Expose RP2040-internal temperature ADC on I2C-over-USB bus?
- [x] Expose RP2040-internal temperature ADC on I2C-over-USB bus?
- [ ] ~~Does SMBus stuff need special treatment here?~~ ~~No.~~ Actually, some
parts do, but, laziness.
- [x] 10-bit I2C address support (Needs poking at the Pico SDK, as it only

View File

@ -28,9 +28,20 @@ void tempsense_dev_init(void) {
int16_t tempsense_dev_get_temp(void) {
adc_select_input(4); // select temp sensor
uint16_t result = adc_read();
int temperature = float2fix(T_OFF - T_BIAS / T_SLOPE)
+ (int)result * float2fix(V_MAX / (D_RANGE * T_SLOPE));
return trunc_8fix4(temperature);
float voltage = result * (V_MAX / D_RANGE);
float tempf = T_OFF + (voltage - T_BIAS) / T_SLOPE;
// FIXME: use fixed point instead! but something's wrong with the formula below
/*int temperature = float2fix(T_OFF - T_BIAS / T_SLOPE)
+ (int)result * float2fix(V_MAX / (D_RANGE * T_SLOPE));*/
return trunc_8fix4(/*temperature*/float2fix(tempf));
}
// RP2040 absolute min/max are -20/85
int16_t tempsense_dev_get_lower(void) { return trunc_8fix4(float2fix(-15)); }
int16_t tempsense_dev_get_upper(void) { return trunc_8fix4(float2fix( 75)); }
int16_t tempsense_dev_get_crit (void) { return trunc_8fix4(float2fix( 80)); }

1
src/t/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
tstest

67
src/t/tstest.c Normal file
View File

@ -0,0 +1,67 @@
#define DBOARD_HAS_TEMPSENSOR
#define VERY_FAKE
#include <stdint.h>
static inline void tempsense_dev_init(void) { }
static inline int16_t tempsense_dev_get_temp(void) { return 42 << 4; }
static inline int16_t tempsense_dev_get_lower(void) { return 0 << 4; }
static inline int16_t tempsense_dev_get_upper(void) { return 75 << 4; }
static inline int16_t tempsense_dev_get_crit (void) { return 80 << 4; }
#include "../tempsensor.c"
static int do_pkt(uint8_t cmd, bool read, uint16_t addr, uint16_t len, uint8_t* buf) {
int rv;
if (cmd & 1) tempsense_do_start();
if (read) {
rv = tempsense_do_read(len, buf);
} else {
rv = tempsense_do_write(len, buf);
}
if (cmd & 2) tempsense_do_stop();
printf("-> %d: %s\n", rv, (rv < 0 || rv != len) ? "nak" : "ack");
return rv;
}
static void pbuf(size_t len, const uint8_t* buf) {
printf("--> ");
size_t i;
for (i = 0; i < len; ++i) {
printf("%02x ", buf[i]);
if ((i & 0xf) == 0xf) printf("%c", '\n');
}
if ((i & 0xf) != 0x0) printf("%c", '\n');
}
int main(int argc, char* argv[]) {
tempsense_init();
tempsense_set_addr(0x18);
// initial probe
uint8_t pk1[1] = {0}; do_pkt(0x05, false, 0x18, 1, pk1);
uint8_t pk2[2]; do_pkt(0x06, true , 0x18, 2, pk2); pbuf(2, pk2);
uint8_t pk3[1] = {1}; do_pkt(0x05, false, 0x18, 1, pk3);
uint8_t pk4[2]; do_pkt(0x06, true , 0x18, 2, pk4); pbuf(2, pk4);
// sensor data get
// out 0x05 cmd5
// in 2byte cmd6
// out 0x04 cmd5
// in 2byte cmd6
// out 0x03 cmd5
// in 2byte cmd6
// out 0x02 cmd5
// in 2byte cmd6
}

View File

@ -4,7 +4,10 @@
#include <stdbool.h>
#include <stdio.h>
#ifndef VERY_FAKE
#include "protocfg.h"
#define printf(fmt, ...) do{}while(0)
#endif
#ifdef DBOARD_HAS_TEMPSENSOR
@ -17,7 +20,8 @@ static size_t index;
static bool instartstop, hasreg;
enum regid {
config = 1,
cap = 0,
config,
t_upper,
t_lower,
t_crit,
@ -36,6 +40,13 @@ struct {
uint8_t reso;
} mcp9808;
#define float2fix(x) (int)((x)*(1<<4))
__attribute__((__const__))
inline static int16_t trunc_8fix4(int fix) {
if (fix > 4095) fix = 4095;
if (fix < -4096) fix = -4096;
return fix;
}
void tempsense_init(void) {
active = false;
addr = 0xff;
@ -45,6 +56,10 @@ void tempsense_init(void) {
hasreg = false;
tempsense_dev_init();
mcp9808.t_lower = tempsense_dev_get_lower();
mcp9808.t_upper = tempsense_dev_get_upper();
mcp9808.t_crit = tempsense_dev_get_crit ();
}
bool tempsense_get_active(void) { return active; }
@ -57,16 +72,20 @@ void tempsense_set_addr(uint8_t a) {
}
void tempsense_do_start(void) {
printf("ts start\n");
//reg = 0;
index = 0;
instartstop = true;
hasreg = false;
}
void tempsense_do_stop(void) {
printf("ts stop\n");
instartstop = false;
}
int tempsense_do_read(int length, uint8_t* buf) {
printf("read l=%d reg=%02x ", length, reg);
if (!instartstop || length < 0) return -1; // nak
if (length == 0) return 0; // ack
//if (!hasreg) return -1; // nak
@ -75,22 +94,29 @@ int tempsense_do_read(int length, uint8_t* buf) {
for (i = 0; i < length; ++i, ++index) {
switch (reg) {
// TODO: big or little endian? seems to be big
case cap:
buf[index] = 0;
break;
case config:
if (index == 0) buf[0] = (mcp9808.config >> 8) & 0xff;
else if (index == 1) buf[1] = (mcp9808.config >> 0) & 0xff;
else return index;
break;
case t_upper:
if (index == 0) buf[0] = (mcp9808.t_upper >> 8) & 0xff;
else if (index == 1) buf[1] = (mcp9808.t_upper >> 0) & 0xff;
else return index;
break;
case t_lower:
if (index == 0) buf[0] = (mcp9808.t_lower >> 8) & 0xff;
else if (index == 1) buf[1] = (mcp9808.t_lower >> 0) & 0xff;
else return index;
break;
case t_crit:
if (index == 0) buf[0] = (mcp9808.t_crit >> 8) & 0xff;
else if (index == 1) buf[1] = (mcp9808.t_crit >> 0) & 0xff;
else return index;
break;
case t_a: {
static uint16_t temp;
if (index == 0) {
@ -113,17 +139,21 @@ int tempsense_do_read(int length, uint8_t* buf) {
} else if (index == 1) buf[1] = (temp>>0) & 0xff;
else return index;
}
break;
case manuf_id:
if (index == 0) buf[0] = (MANUF_ID >> 8) & 0xff;
else if (index == 1) buf[1] = (MANUF_ID>>0)&0xff;
else return index;
break;
case dev_idrev:
if (index == 0) buf[0] = (DEV_IDREV >> 8) & 0xff;
else if (index == 1) buf[1] = (DEV_IDREV>>0)&0xff;
else return index;
break;
case reso:
if (index == 0) buf[0] = mcp9808.reso;
else return index;
break;
default: return -1;
}
}
@ -131,10 +161,14 @@ int tempsense_do_read(int length, uint8_t* buf) {
return i;
}
int tempsense_do_write(int length, const uint8_t* buf) {
printf("write l=%d reg=%02x iss=%c ", length, reg, instartstop?'t':'f');
if (!instartstop || length < 0) return -1; // nak
if (length == 0) return 0; // ack
if (!hasreg) {
printf("get reg %02x ", reg);
reg = *buf & 0xf;
++buf;
--length;
@ -152,27 +186,34 @@ int tempsense_do_write(int length, const uint8_t* buf) {
} else if (index == 1) {
mcp9808.config = (mcp9808.config & 0xff00) | ((uint16_t)buf[1] << 0);
} else return index;
break;
case t_upper:
if (index == 0) {
mcp9808.t_upper = (mcp9808.t_upper & 0x00ff) | ((uint16_t)buf[0] << 8);
} else if (index == 1) {
mcp9808.t_upper = (mcp9808.t_upper & 0xff00) | ((uint16_t)buf[1] << 0);
} else return index;
break;
case t_lower:
if (index == 0) {
mcp9808.t_lower = (mcp9808.t_lower & 0x00ff) | ((uint16_t)buf[0] << 8);
} else if (index == 1) {
mcp9808.t_lower = (mcp9808.t_lower & 0xff00) | ((uint16_t)buf[1] << 0);
} else return index;
break;
case t_crit:
if (index == 0) {
mcp9808.t_crit = (mcp9808.t_crit & 0x00ff) | ((uint16_t)buf[0] << 8);
} else if (index == 1) {
mcp9808.t_crit = (mcp9808.t_crit & 0xff00) | ((uint16_t)buf[1] << 0);
} else return index;
break;
case reso:
mcp9808.reso = buf[index];
default: return -1;
break;
default:
printf("unk reg\n");
return -1;
}
}

View File

@ -21,6 +21,10 @@ void tempsense_do_stop(void); // stop cond
void tempsense_dev_init(void);
// 8.4
int16_t tempsense_dev_get_temp(void);
int16_t tempsense_dev_get_lower(void);
int16_t tempsense_dev_get_upper(void);
int16_t tempsense_dev_get_crit (void);
#endif
#endif

View File

@ -85,7 +85,10 @@ static bool iub_ctl_req(uint8_t rhport, uint8_t stage, tusb_control_request_t co
#ifdef DBOARD_HAS_TEMPSENSOR
if (tempsense_get_active() && tempsense_get_addr() == cmd.addr) {
if (cmd.cmd & ITU_CMD_I2C_IO_BEGIN_F) tempsense_do_start();
status = tempsense_do_write(cmd.len > sizeof rxbuf ? sizeof rxbuf : cmd.len, rxbuf);
// FIXME: fix status handling
int rv = tempsense_do_write(cmd.len > sizeof rxbuf ? sizeof rxbuf : cmd.len, rxbuf);
if (rv < 0 || rv != cmd.len) status = ITU_STATUS_ADDR_NAK;
else status = ITU_STATUS_ADDR_ACK;
if (cmd.cmd & ITU_CMD_I2C_IO_END_F ) tempsense_do_stop ();
} else
#endif
@ -155,7 +158,9 @@ static bool iub_ctl_req(uint8_t rhport, uint8_t stage, tusb_control_request_t co
#ifdef DBOARD_HAS_TEMPSENSOR
if (tempsense_get_active() && tempsense_get_addr() == cmd.addr) {
if (cmd.cmd & ITU_CMD_I2C_IO_BEGIN_F) tempsense_do_start();
status = tempsense_do_read(cmd.len > sizeof txbuf ? sizeof txbuf : cmd.len, txbuf);
int rv = tempsense_do_read(cmd.len > sizeof txbuf ? sizeof txbuf : cmd.len, txbuf);
if (rv < 0 || rv != cmd.len) status = ITU_STATUS_ADDR_NAK;
else status = ITU_STATUS_ADDR_ACK;
if (cmd.cmd & ITU_CMD_I2C_IO_END_F ) tempsense_do_stop ();
} else
#endif
@ -173,7 +178,9 @@ static bool iub_ctl_req(uint8_t rhport, uint8_t stage, tusb_control_request_t co
#ifdef DBOARD_HAS_TEMPSENSOR
if (tempsense_get_active() && tempsense_get_addr() == cmd.addr) {
if (cmd.cmd & ITU_CMD_I2C_IO_BEGIN_F) tempsense_do_start();
status = tempsense_do_write(0, &bleh);
int rv = tempsense_do_write(0, &bleh);
if (rv < 0 || rv != cmd.len) status = ITU_STATUS_ADDR_NAK;
else status = ITU_STATUS_ADDR_ACK;
if (cmd.cmd & ITU_CMD_I2C_IO_END_F ) tempsense_do_stop ();
} else
#endif