-- Sound Terrain Grid 128 / iii 1.1: channel 16, 1-based physical coordinates.
-- CC118=1 handshake request/reply; CC118=2 wrong size; CC119 commit frame.
-- Note 0..127: key events outward, brightness 0..15 inward.
metro.free_all()
local valid=grid_size_x()==16 and grid_size_y()==8
local online=false
local last_frame=0
grid_led_all(0)
grid_refresh()
function event_grid(x,y,z)
  if not valid or not online then return end
  if x<1 or x>16 or y<1 or y>8 then return end
  midi_out({z>0 and 0x9f or 0x8f,(x-1)+(y-1)*16,z>0 and 127 or 0})
end
function event_midi(status,a,b)
  if status==0xbf and a==118 and b==1 then
    online=valid
    last_frame=get_time()
    midi_out({0xbf,118,valid and 1 or 2})
    return
  end
  if not valid or not online then return end
  if status==0x9f and a>=0 and a<128 then
    grid_led(a%16+1,math.floor(a/16)+1,math.min(15,b))
  elseif status==0xbf and a==119 then
    last_frame=get_time()
    grid_refresh()
  end
end
local watch=metro.init(function()
  if online and get_time()-last_frame>2 then
    grid_led_all(0);grid_refresh()
  end
end,0.25)
watch:start()
