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),
				)
			}
		}
	}
}
