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 up in `sensors`, do the following (with `BUSNUM` the number from the above
`i2cdetect -l` output): `i2cdetect -l` output):
``` ```
$ ./dmctl.py /dev/ttyACM1 --i2ctemp 0x18 # need to give it an address first
$ sudo modprobe jc42 $ 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 $ 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 ### 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 - `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 sensor. Use 0 for getting the value, 0xff for disabling, and any
other for setting the address. The I2C device emulated is an MCP9808. 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 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. to use the UART interface as a loopback thing.
- [ ] Second UART port for when stdio UART is disabled? - [ ] Second UART port for when stdio UART is disabled?
- [x] I2C support by emulating the I2C Tiny USB - [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 - [ ] ~~Does SMBus stuff need special treatment here?~~ ~~No.~~ Actually, some
parts do, but, laziness. parts do, but, laziness.
- [x] 10-bit I2C address support (Needs poking at the Pico SDK, as it only - [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) { int16_t tempsense_dev_get_temp(void) {
adc_select_input(4); // select temp sensor adc_select_input(4); // select temp sensor
uint16_t result = adc_read(); 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 <stdbool.h>
#include <stdio.h> #include <stdio.h>
#ifndef VERY_FAKE
#include "protocfg.h" #include "protocfg.h"
#define printf(fmt, ...) do{}while(0)
#endif
#ifdef DBOARD_HAS_TEMPSENSOR #ifdef DBOARD_HAS_TEMPSENSOR
@ -17,7 +20,8 @@ static size_t index;
static bool instartstop, hasreg; static bool instartstop, hasreg;
enum regid { enum regid {
config = 1, cap = 0,
config,
t_upper, t_upper,
t_lower, t_lower,
t_crit, t_crit,
@ -36,6 +40,13 @@ struct {
uint8_t reso; uint8_t reso;
} mcp9808; } 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) { void tempsense_init(void) {
active = false; active = false;
addr = 0xff; addr = 0xff;
@ -45,6 +56,10 @@ void tempsense_init(void) {
hasreg = false; hasreg = false;
tempsense_dev_init(); 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; } bool tempsense_get_active(void) { return active; }
@ -57,16 +72,20 @@ void tempsense_set_addr(uint8_t a) {
} }
void tempsense_do_start(void) { void tempsense_do_start(void) {
printf("ts start\n");
//reg = 0; //reg = 0;
index = 0; index = 0;
instartstop = true; instartstop = true;
hasreg = false; hasreg = false;
} }
void tempsense_do_stop(void) { void tempsense_do_stop(void) {
printf("ts stop\n");
instartstop = false; instartstop = false;
} }
int tempsense_do_read(int length, uint8_t* buf) { 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 (!instartstop || length < 0) return -1; // nak
if (length == 0) return 0; // ack if (length == 0) return 0; // ack
//if (!hasreg) return -1; // nak //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) { for (i = 0; i < length; ++i, ++index) {
switch (reg) { switch (reg) {
// TODO: big or little endian? seems to be big // TODO: big or little endian? seems to be big
case cap:
buf[index] = 0;
break;
case config: case config:
if (index == 0) buf[0] = (mcp9808.config >> 8) & 0xff; if (index == 0) buf[0] = (mcp9808.config >> 8) & 0xff;
else if (index == 1) buf[1] = (mcp9808.config >> 0) & 0xff; else if (index == 1) buf[1] = (mcp9808.config >> 0) & 0xff;
else return index; else return index;
break;
case t_upper: case t_upper:
if (index == 0) buf[0] = (mcp9808.t_upper >> 8) & 0xff; if (index == 0) buf[0] = (mcp9808.t_upper >> 8) & 0xff;
else if (index == 1) buf[1] = (mcp9808.t_upper >> 0) & 0xff; else if (index == 1) buf[1] = (mcp9808.t_upper >> 0) & 0xff;
else return index; else return index;
break;
case t_lower: case t_lower:
if (index == 0) buf[0] = (mcp9808.t_lower >> 8) & 0xff; if (index == 0) buf[0] = (mcp9808.t_lower >> 8) & 0xff;
else if (index == 1) buf[1] = (mcp9808.t_lower >> 0) & 0xff; else if (index == 1) buf[1] = (mcp9808.t_lower >> 0) & 0xff;
else return index; else return index;
break;
case t_crit: case t_crit:
if (index == 0) buf[0] = (mcp9808.t_crit >> 8) & 0xff; if (index == 0) buf[0] = (mcp9808.t_crit >> 8) & 0xff;
else if (index == 1) buf[1] = (mcp9808.t_crit >> 0) & 0xff; else if (index == 1) buf[1] = (mcp9808.t_crit >> 0) & 0xff;
else return index; else return index;
break;
case t_a: { case t_a: {
static uint16_t temp; static uint16_t temp;
if (index == 0) { 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 if (index == 1) buf[1] = (temp>>0) & 0xff;
else return index; else return index;
} }
break;
case manuf_id: case manuf_id:
if (index == 0) buf[0] = (MANUF_ID >> 8) & 0xff; if (index == 0) buf[0] = (MANUF_ID >> 8) & 0xff;
else if (index == 1) buf[1] = (MANUF_ID>>0)&0xff; else if (index == 1) buf[1] = (MANUF_ID>>0)&0xff;
else return index; else return index;
break;
case dev_idrev: case dev_idrev:
if (index == 0) buf[0] = (DEV_IDREV >> 8) & 0xff; if (index == 0) buf[0] = (DEV_IDREV >> 8) & 0xff;
else if (index == 1) buf[1] = (DEV_IDREV>>0)&0xff; else if (index == 1) buf[1] = (DEV_IDREV>>0)&0xff;
else return index; else return index;
break;
case reso: case reso:
if (index == 0) buf[0] = mcp9808.reso; if (index == 0) buf[0] = mcp9808.reso;
else return index; else return index;
break;
default: return -1; default: return -1;
} }
} }
@ -131,10 +161,14 @@ int tempsense_do_read(int length, uint8_t* buf) {
return i; return i;
} }
int tempsense_do_write(int length, const uint8_t* buf) { 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 (!instartstop || length < 0) return -1; // nak
if (length == 0) return 0; // ack if (length == 0) return 0; // ack
if (!hasreg) { if (!hasreg) {
printf("get reg %02x ", reg);
reg = *buf & 0xf; reg = *buf & 0xf;
++buf; ++buf;
--length; --length;
@ -152,27 +186,34 @@ int tempsense_do_write(int length, const uint8_t* buf) {
} else if (index == 1) { } else if (index == 1) {
mcp9808.config = (mcp9808.config & 0xff00) | ((uint16_t)buf[1] << 0); mcp9808.config = (mcp9808.config & 0xff00) | ((uint16_t)buf[1] << 0);
} else return index; } else return index;
break;
case t_upper: case t_upper:
if (index == 0) { if (index == 0) {
mcp9808.t_upper = (mcp9808.t_upper & 0x00ff) | ((uint16_t)buf[0] << 8); mcp9808.t_upper = (mcp9808.t_upper & 0x00ff) | ((uint16_t)buf[0] << 8);
} else if (index == 1) { } else if (index == 1) {
mcp9808.t_upper = (mcp9808.t_upper & 0xff00) | ((uint16_t)buf[1] << 0); mcp9808.t_upper = (mcp9808.t_upper & 0xff00) | ((uint16_t)buf[1] << 0);
} else return index; } else return index;
break;
case t_lower: case t_lower:
if (index == 0) { if (index == 0) {
mcp9808.t_lower = (mcp9808.t_lower & 0x00ff) | ((uint16_t)buf[0] << 8); mcp9808.t_lower = (mcp9808.t_lower & 0x00ff) | ((uint16_t)buf[0] << 8);
} else if (index == 1) { } else if (index == 1) {
mcp9808.t_lower = (mcp9808.t_lower & 0xff00) | ((uint16_t)buf[1] << 0); mcp9808.t_lower = (mcp9808.t_lower & 0xff00) | ((uint16_t)buf[1] << 0);
} else return index; } else return index;
break;
case t_crit: case t_crit:
if (index == 0) { if (index == 0) {
mcp9808.t_crit = (mcp9808.t_crit & 0x00ff) | ((uint16_t)buf[0] << 8); mcp9808.t_crit = (mcp9808.t_crit & 0x00ff) | ((uint16_t)buf[0] << 8);
} else if (index == 1) { } else if (index == 1) {
mcp9808.t_crit = (mcp9808.t_crit & 0xff00) | ((uint16_t)buf[1] << 0); mcp9808.t_crit = (mcp9808.t_crit & 0xff00) | ((uint16_t)buf[1] << 0);
} else return index; } else return index;
break;
case reso: case reso:
mcp9808.reso = buf[index]; 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); void tempsense_dev_init(void);
// 8.4 // 8.4
int16_t tempsense_dev_get_temp(void); 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
#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 #ifdef DBOARD_HAS_TEMPSENSOR
if (tempsense_get_active() && tempsense_get_addr() == cmd.addr) { if (tempsense_get_active() && tempsense_get_addr() == cmd.addr) {
if (cmd.cmd & ITU_CMD_I2C_IO_BEGIN_F) tempsense_do_start(); 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 (); if (cmd.cmd & ITU_CMD_I2C_IO_END_F ) tempsense_do_stop ();
} else } else
#endif #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 #ifdef DBOARD_HAS_TEMPSENSOR
if (tempsense_get_active() && tempsense_get_addr() == cmd.addr) { if (tempsense_get_active() && tempsense_get_addr() == cmd.addr) {
if (cmd.cmd & ITU_CMD_I2C_IO_BEGIN_F) tempsense_do_start(); 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 (); if (cmd.cmd & ITU_CMD_I2C_IO_END_F ) tempsense_do_stop ();
} else } else
#endif #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 #ifdef DBOARD_HAS_TEMPSENSOR
if (tempsense_get_active() && tempsense_get_addr() == cmd.addr) { if (tempsense_get_active() && tempsense_get_addr() == cmd.addr) {
if (cmd.cmd & ITU_CMD_I2C_IO_BEGIN_F) tempsense_do_start(); 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 (); if (cmd.cmd & ITU_CMD_I2C_IO_END_F ) tempsense_do_stop ();
} else } else
#endif #endif