package main // Thermal camera example using AMG88xx 8x8 IR sensor. // Connect the sensor to I2C1: SDA=P0_17, SCL=P0_20 (3.3V power). // // The 8x8 sensor data is scaled to 24x24 with bilinear interpolation and // rendered with an iron-palette color map on the 240x135 display. // Each scaled pixel is drawn as a 10x5 px block → 240x120 total, centered. import ( "image" "machine" draw2 "golang.org/x/image/draw" "tinygo.org/x/drivers/amg88xx" "tinygo.org/x/drivers/st7789" ) const ( sensorSize = 8 // AMG88xx is 8x8 scaledSize = 24 // intermediate bilinear-scaled image blockW = 10 // px per scaled pixel (horizontal): 24*10 = 240 blockH = 5 // px per scaled pixel (vertical): 24*5 = 120 yOffset = 7 // center 120px vertically in 135px display: (135-120)/2 ) var ( display st7789.Device data [sensorSize * sensorSize]int16 ) func main() { machine.SPI0.Configure(machine.SPIConfig{ SCK: machine.P1_01, SDO: machine.P1_02, Frequency: 8000000, Mode: 0, }) machine.I2C1.Configure(machine.I2CConfig{ SDA: machine.P0_17, SCL: machine.P0_20, Frequency: 400000, }) display = st7789.New(machine.SPI0, machine.P1_15, // TFT_RESET machine.P1_13, // TFT_DC machine.P0_10, // TFT_CS machine.P0_09) // TFT_LITE display.Configure(st7789.Config{ Rotation: st7789.ROTATION_90, Width: 135, Height: 240, RowOffset: 40, ColumnOffset: 53, }) camera := amg88xx.New(machine.I2C1) camera.Configure(amg88xx.Config{}) src := image.NewRGBA(image.Rect(0, 0, sensorSize, sensorSize)) dst := image.NewRGBA(image.Rect(0, 0, scaledSize, scaledSize)) for { camera.ReadPixels(&data) // map each sensor pixel to a palette color for j := 0; j < sensorSize; j++ { for i := 0; i < sensorSize; i++ { v := data[63-(i+j*sensorSize)] // clamp to 18°C–33°C range → index 0–432 if v < 18000 { v = 0 } else { v = (v - 18000) / 36 if v > 432 { v = 432 } } src.Set(i, j, colors[v]) } } // bilinear upscale 8x8 → 24x24 draw2.BiLinear.Scale(dst, dst.Bounds(), src, src.Bounds(), draw2.Over, nil) // draw horizontally mirrored (acts as a selfie mirror) for j := 0; j < scaledSize; j++ { for i := 0; i < scaledSize; i++ { display.FillRectangle( int16((scaledSize-1-i)*blockW), yOffset+int16(j)*blockH, blockW, blockH, dst.RGBAAt(i, j), ) } } } }