Of course, I was mixing up the timings with the phase corrected modes. Clearly I need to toggle in CTC.
I actually find these mnemonics are just as cryptic as plain binary: remembering what WMG12 means is the same as remembering what TCCR1B does except that I need to learn two names instead of one. (Not Arduinos fault, that's the Atmel doc) but it's as cryptic a binary at the end of the day.
I either need to define some const values that are human readable (which is probably what Arduino should have done) or liberally spray my code with comments. Until I find out exactly how all this hangs together , it's the latter.
TCCR1A &= (unsigned char)~0b11110011; // zeros are reserved bits
// TCCR1A |= 0b00; // WGM1[1,0] = 0b00, with WGM1[3,2]=01 for CTC; WGM1=0 i/p
TCCR1A |= 0b01000000; // COM1A[1,0]= TCCR1A[7.6]=01; COM1B[1,0]= TCCR1A[5,4]=00 ; normal DIO
// COM1A[1,0]= 01 ; toggle output to chk freq on pin 9 //
// TCCR1B[7,6] : input capture only, noise filter , edge detection.  reserved
TCCR1B &= ~0b11011111; // [7,6] noise canceller=0;  resv.
TCCR1B |= 0b01101; // 01101: WGM2[3,2]=01 + "div 1024" -> 16kHz tick: OCR1A sets count ...
OCR1A = 16; // set cycle length = 16kHz /16/2 = circa 1/2 kHz
TIMSK1 = 0b001; // in CTC, TOIE1 bit: TOV1 triggers at MAX, ie OCR1A match
That seems to be the same as what you posted.
My TIMER1_OVF_vect() is getting called now as I intended. And I get 500Hz on pin 9
Thanks for your help in seeing this silly error.