#include <FastLED.h>

#define WIDTH 8
#define HEIGHT 8
#define NUM_LEDS ((WIDTH) * (HEIGHT))
CRGB leds[NUM_LEDS];

void setup() {
  FastLED.addLeds<NEOPIXEL, PB1>(leds, NUM_LEDS);
}

// map X & Y coordinates onto a horizontal serpentine matrix layout
uint8_t XY(uint8_t x, uint8_t y) {
  if (y & 1)
    return (y + 1) * WIDTH - x - 1;
  return y * WIDTH + x;
}

void loop() {
  const float pi = 3.14159265;
  static uint16_t z_offset = 0;  // animates the effect by changing the Z coordinate of the noise
  float angle_factor = 650.f;    // affects density around the circular axis 
  float distance_factor = 32.f;  // affects density along distance from the centre 
  for (int8_t y = 0; y < HEIGHT; y++) {
    for (int8_t x = 0; x < WIDTH; x++) {
      // move the origin to the centre of the matrix
      float cx = x - (WIDTH / 2 - 0.5f);
      float cy = y - (HEIGHT / 2 - 0.5f);
      // find the polar coords for this pixel's cartesian coords
      uint16_t angle = (pi + atan2f(cy, cx)) * (angle_factor / pi / 2.f);
      uint16_t distance = hypotf(cy, cx) * (distance_factor / hypotf(WIDTH / 2, HEIGHT / 2));
      // map 3D Perlin simplex noise onto the polar coords
      leds[XY(x, y)] = ColorFromPalette(HeatColors_p, inoise8(angle, distance, z_offset));
    }
  }
  FastLED.show();
  z_offset += 8;  // move the Z axis of the noise slightly
}
ATTINY8520PU