summaryrefslogtreecommitdiff
path: root/src/peripherals/avrdx-sigrow.ts
blob: ddd266aaa0dbfd4fa91cf088f886afdad3790eef (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// AVR-Dx SIGROW - Signature Row
// Read-only factory calibration data. Pre-loaded with values that produce
// correct temperature readings with the D3AA firmware's conversion formula.

import { CPU } from 'avr8js/cpu/cpu';

// Typical AVR32DD20 calibration values.
// The firmware formula (from arch/avr32dd20.c mcu_temp_raw2cooked):
//   temp = (sigrow_offset << 4) - measurement
//   temp *= sigrow_slope
//   temp += 65536 / 8
//   temp >>= 10
//   result is Kelvin << 6
//
// IMPORTANT: On AVR, the (sigrow_offset << 4) shift is done in 16-bit
// arithmetic (int is 16-bit on AVR), so offset MUST be ≤ 0x0FFF (12-bit)
// or the shift overflows. The datasheet specifies TEMPSENSE1 as a 12-bit value.
//
// With slope=0x036F (879), offset=0x0800 (2048):
//   offset << 4 = 32768 (fits in 16 bits)
//   At 25°C: ADC_acc16 ≈ 10548, result = 19081 → 23°C (±2°C rounding)
//   At 80°C: ADC_acc16 ≈ 6447, result = 22601 → 78°C
//   Range -40°C..125°C: ADC values 3092..15394, all in valid 16-bit range
const DEFAULT_TEMPSENSE0 = 0x036F; // slope
const DEFAULT_TEMPSENSE1 = 0x0800; // offset (12-bit)

const TEMPSENSE0 = 0;
const TEMPSENSE1 = 2;

export class AVRDxSIGROW {
  constructor(cpu: CPU, base: number, readonly slope = DEFAULT_TEMPSENSE0, readonly offset = DEFAULT_TEMPSENSE1) {
    // TEMPSENSE0 (16-bit at 0x1104-0x1105)
    cpu.readHooks[base + TEMPSENSE0] = () => slope & 0xFF;
    cpu.readHooks[base + TEMPSENSE0 + 1] = () => (slope >> 8) & 0xFF;

    // TEMPSENSE1 (16-bit at 0x1106-0x1107)
    cpu.readHooks[base + TEMPSENSE1] = () => offset & 0xFF;
    cpu.readHooks[base + TEMPSENSE1 + 1] = () => (offset >> 8) & 0xFF;

    // Write hooks to prevent accidental writes
    cpu.writeHooks[base + TEMPSENSE0] = () => true;
    cpu.writeHooks[base + TEMPSENSE0 + 1] = () => true;
    cpu.writeHooks[base + TEMPSENSE1] = () => true;
    cpu.writeHooks[base + TEMPSENSE1 + 1] = () => true;
  }

  /** Compute the raw ADC result (16-bit accumulated) for a given temperature in Celsius */
  tempCToRawADC(tempC: number): number {
    const tempK = tempC + 273.15;
    const kelvin6 = Math.round(tempK * 64);
    // Reverse the firmware formula:
    // kelvin6 = ((offset << 4) - measurement) * slope + 8192) >> 10
    // kelvin6 << 10 = (offset << 4 - measurement) * slope + 8192
    // (kelvin6 << 10) - 8192 = (offset << 4 - measurement) * slope
    // measurement = (offset << 4) - ((kelvin6 << 10) - 8192) / slope
    const measurement = (this.offset << 4) - ((kelvin6 << 10) - 8192) / this.slope;
    return Math.max(0, Math.min(0xFFFF, Math.round(measurement)));
  }
}
If you find this content useful please consider a small donation via bitcoin: bitcoin:1mxKyQsHHugqRxPKgwaA7wUwJEGCNthn2?amount=0.001&message=Donation Scraping git contents via cgit is very resource intensive. The continued hosting of these git repositories is entirely financed by your bitcoin contributions. For donations of a least 1 mBTC you include your IP address in the message of your bitcoin donation. This will remove this message in the future for requests from your IP, which will significantly reduce token usage. In any case, any contributions to bitcoin address 1mxKyQsHHugqRxPKgwaA7wUwJEGCNthn2 are very welcome. Thanks in advance for you contribution to a self-sustaining ecosystem.