/*
Copyright (C) 2014 <>< Charles Lohr
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#define F_CPU 29000000UL
const unsigned char font_8x8_data[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 1
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 2
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 3
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 4
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 5
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 6
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 7
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 8
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 9
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 10
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 11
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 12
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 13
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 14
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 15
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 16
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 17
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 18
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 19
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 20
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 21
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 22
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 23
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 24
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 25
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 26
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 27
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 28
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 29
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 30
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 31
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ' '
0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, // '!'
0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // '"'
0x28, 0x28, 0xfe, 0x28, 0xfe, 0x28, 0x28, 0x00, // '#'
0x10, 0x78, 0x14, 0x38, 0x50, 0x3c, 0x10, 0x00, // '$'
0x00, 0x4c, 0x2c, 0x10, 0x68, 0x64, 0x00, 0x00, // '%'
0x18, 0x14, 0x08, 0x14, 0x62, 0x22, 0x5c, 0x00, // '&'
0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // '''
0x20, 0x10, 0x08, 0x08, 0x08, 0x10, 0x20, 0x00, // '('
0x08, 0x10, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00, // ')'
0x10, 0x92, 0x54, 0x38, 0x54, 0x92, 0x10, 0x00, // '*'
0x10, 0x10, 0x10, 0xfe, 0x10, 0x10, 0x10, 0x00, // '+'
0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x20, 0x10, // ','
0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, // '-'
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, // '.'
0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, // '/'
0x38, 0x44, 0x44, 0x54, 0x44, 0x44, 0x38, 0x00, // '0'
0x10, 0x18, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, // '1'
0x38, 0x44, 0x40, 0x20, 0x10, 0x08, 0x7c, 0x00, // '2'
0x38, 0x44, 0x40, 0x30, 0x40, 0x44, 0x38, 0x00, // '3'
0x30, 0x28, 0x24, 0x7c, 0x20, 0x20, 0x70, 0x00, // '4'
0x7c, 0x04, 0x04, 0x3c, 0x40, 0x44, 0x38, 0x00, // '5'
0x38, 0x44, 0x04, 0x3c, 0x44, 0x44, 0x38, 0x00, // '6'
0x7c, 0x40, 0x20, 0x10, 0x08, 0x08, 0x08, 0x00, // '7'
0x38, 0x44, 0x44, 0x38, 0x44, 0x44, 0x38, 0x00, // '8'
0x38, 0x44, 0x44, 0x78, 0x40, 0x44, 0x38, 0x00, // '9'
0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x00, 0x00, // ':'
0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x20, 0x10, // ';'
0x20, 0x10, 0x08, 0x04, 0x08, 0x10, 0x20, 0x00, // '<'
0x00, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, // '='
0x04, 0x08, 0x10, 0x20, 0x10, 0x08, 0x04, 0x00, // '>'
0x38, 0x44, 0x40, 0x20, 0x10, 0x00, 0x10, 0x00, // '?'
0x38, 0x44, 0x74, 0x54, 0x74, 0x04, 0x38, 0x00, // '@'
0x38, 0x44, 0x44, 0x7c, 0x44, 0x44, 0x44, 0x00, // 'A'
0x3c, 0x44, 0x44, 0x3c, 0x44, 0x44, 0x3c, 0x00, // 'B'
0x38, 0x44, 0x04, 0x04, 0x04, 0x44, 0x38, 0x00, // 'C'
0x3c, 0x44, 0x44, 0x44, 0x44, 0x44, 0x3c, 0x00, // 'D'
0x7c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x7c, 0x00, // 'E'
0x7c, 0x04, 0x04, 0x7c, 0x04, 0x04, 0x04, 0x00, // 'F'
0x38, 0x44, 0x04, 0x74, 0x44, 0x44, 0x38, 0x00, // 'G'
0x44, 0x44, 0x44, 0x7c, 0x44, 0x44, 0x44, 0x00, // 'H'
0x38, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, // 'I'
0x70, 0x20, 0x20, 0x20, 0x24, 0x24, 0x18, 0x00, // 'J'
0x44, 0x44, 0x24, 0x1c, 0x24, 0x44, 0x44, 0x00, // 'K'
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x78, 0x00, // 'L'
0x82, 0xc6, 0xaa, 0x92, 0x82, 0x82, 0x82, 0x00, // 'M'
0x44, 0x4c, 0x54, 0x54, 0x64, 0x44, 0x44, 0x00, // 'N'
0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, // 'O'
0x38, 0x48, 0x48, 0x38, 0x08, 0x08, 0x08, 0x00, // 'P'
0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x60, // 'Q'
0x3c, 0x44, 0x44, 0x3c, 0x14, 0x24, 0x44, 0x00, // 'R'
0x38, 0x44, 0x04, 0x38, 0x40, 0x44, 0x38, 0x00, // 'S'
0x7c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, // 'T'
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, // 'U'
0x44, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x00, // 'V'
0x82, 0x82, 0x82, 0x54, 0x54, 0x28, 0x28, 0x00, // 'W'
0x44, 0x44, 0x28, 0x10, 0x28, 0x44, 0x44, 0x00, // 'X'
0x44, 0x44, 0x28, 0x10, 0x10, 0x10, 0x10, 0x00, // 'Y'
0x7c, 0x40, 0x20, 0x10, 0x08, 0x04, 0x7c, 0x00, // 'Z'
0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, // '['
0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, // '\'
0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38, 0x00, // ']'
0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, // '^'
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, // '_'
0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // '`'
0x00, 0x38, 0x40, 0x78, 0x44, 0x44, 0xb8, 0x00, // 'a'
0x08, 0x08, 0x38, 0x48, 0x48, 0x48, 0x34, 0x00, // 'b'
0x00, 0x00, 0x38, 0x04, 0x04, 0x04, 0x38, 0x00, // 'c'
0x40, 0x40, 0x70, 0x48, 0x48, 0x48, 0xb0, 0x00, // 'd'
0x00, 0x00, 0x38, 0x44, 0x7c, 0x04, 0x38, 0x00, // 'e'
0x30, 0x48, 0x08, 0x1c, 0x08, 0x08, 0x08, 0x00, // 'f'
0x00, 0x00, 0xb8, 0x44, 0x44, 0x78, 0x40, 0x38, // 'g'
0x04, 0x04, 0x34, 0x4c, 0x44, 0x44, 0x44, 0x00, // 'h'
0x00, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, // 'i'
0x00, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x0c, // 'j'
0x04, 0x04, 0x24, 0x14, 0x0c, 0x14, 0x24, 0x00, // 'k'
0x18, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, // 'l'
0x00, 0x00, 0x6d, 0x92, 0x92, 0x82, 0x82, 0x00, // 'm'
0x00, 0x00, 0x34, 0x48, 0x48, 0x48, 0x48, 0x00, // 'n'
0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, // 'o'
0x00, 0x00, 0x34, 0x48, 0x48, 0x38, 0x08, 0x08, // 'p'
0x00, 0x00, 0x58, 0x24, 0x24, 0x38, 0x20, 0x20, // 'q'
0x00, 0x00, 0x34, 0x0c, 0x04, 0x04, 0x04, 0x00, // 'r'
0x00, 0x00, 0x38, 0x04, 0x18, 0x20, 0x1c, 0x00, // 's'
0x00, 0x10, 0x38, 0x10, 0x10, 0x10, 0x10, 0x00, // 't'
0x00, 0x00, 0x24, 0x24, 0x24, 0x24, 0x58, 0x00, // 'u'
0x00, 0x00, 0x44, 0x44, 0x44, 0x28, 0x10, 0x00, // 'v'
0x00, 0x00, 0x82, 0x82, 0x92, 0xaa, 0x44, 0x00, // 'w'
0x00, 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, 0x00, // 'x'
0x00, 0x00, 0x48, 0x48, 0x48, 0x70, 0x40, 0x38, // 'y'
0x00, 0x00, 0x3c, 0x20, 0x10, 0x08, 0x3c, 0x00, // 'z'
0x30, 0x08, 0x08, 0x04, 0x08, 0x08, 0x30, 0x00, // '{'
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, // '|'
0x0c, 0x10, 0x10, 0x20, 0x10, 0x10, 0x0c, 0x00, // '}'
0x00, 0x00, 0x0c, 0x92, 0x60, 0x00, 0x00, 0x00, // '~'
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ''
};
void delay_ms(uint32_t time) {
uint32_t i;
for (i = 0; i < time; i++) {
_delay_ms(1);
}
}
#define NOOP asm volatile("nop" ::)
void NumToText( char * c, uint8_t a )
{
c[0] = (a/100)+'0';
c[1] = ((a/10)%10)+'0';
c[2] = (a%10)+'0';
c[3] = 0;
}
void NumToText4( char * c, uint16_t a )
{
c[0] = (a/1000)+'0';
c[1] = ((a/100)%10)+'0';
c[2] = ((a/10)%10)+'0';
c[3] = (a%10)+'0';
c[4] = 0;
}
EMPTY_INTERRUPT(TIM0_OVF_vect );
int main( )
{
cli();
CLKPR = 0x80; /*Setup CLKPCE to be receptive*/
CLKPR = 0x00; /*No scalar*/
PLLCSR = _BV(PLLE) | _BV( PCKE );
// PLLCSR |= _BV(LSM);
DDRB = _BV(1);
DDRB |= _BV(3);
DDRB |= _BV(4);
PORTB |= _BV(1);
TCCR1 = _BV(CS10);// | _BV(CTC1); //Clear on trigger.
GTCCR |= _BV(PWM1B) | _BV(COM1B0);// | _BV(COM1B1);
OCR1B = 2;
OCR1C = 3;
DTPS1 = 0;
DT1B = _BV(0) | _BV(4);
TCCR0A = 0;
TCCR0B = _BV(CS01);
TIMSK |= _BV(TOIE0);
OSCCAL = 215;
// OSCCAL=186;
#define POWERSET
#ifdef POWERSET
#define NTSC_HI { DDRB=0;}
#define NTSC_LOW { DDRB=_BV(4); }
#define NTSC_VH { DDRB=_BV(3); }
#elif defined( POWERSET2 )
#define NTSC_VH { DDRB=0;}
#define NTSC_LOW { DDRB=_BV(4)|_BV(3); }
#define NTSC_HI { DDRB=_BV(3); }
#elif defined( POWERSET3 )
#define NTSC_VH { DDRB=0; }
#define NTSC_HI { DDRB=_BV(3); }
#define NTSC_LOW { DDRB=_BV(4)|_BV(3); }
#else
//Experimental mechanisms for changing power. Don't work.
#define NTSC_VH { OCR1C = 3; TCNT1 = 0; }
#define NTSC_HI { OCR1C = 6; TCNT1 = 0;}
#define NTSC_LOW { OCR1C = 0; TCNT1 = 0;}
#endif
uint8_t line, i;
#define TIMEOFFSET .12 //.12
#define CLKOFS .12
uint8_t frame = 0, k, ctll;
char stdsr[8*13];
sprintf( stdsr, "Fr: " );
sprintf( stdsr+8, "HalfByte" );
sprintf( stdsr+16, " Blog " );
sprintf( stdsr+24, " " );
sprintf( stdsr+32, " Trinket" );
sprintf( stdsr+40, "AdaFruit" );
sprintf( stdsr+48, " " );
sprintf( stdsr+56, " " );
sprintf( stdsr+64, " " );
sprintf( stdsr+72, " " );
sprintf( stdsr+80, " " );
sprintf( stdsr+88, " " );
ADMUX =/* _BV(REFS1) | _BV(ADLAR) | */ 1; //1 = PB2
ADCSRA = _BV(ADEN) | _BV(ADSC) | _BV(ADATE) | _BV(ADPS2) | _BV(ADPS1);
#define LINETIME 21 //Linetime of 7..20 is barely valid. So,
//#define WAITTCNT while(TCNT0);
#define RESETCNT {TCNT0 = LINETIME; TIFR|=_BV(TOV0); GTCCR|=PSR0;sei();}
//#define WAITTCNT while(!(TIFR&_BV(TOV0)));
#define WAITTCNT sleep_cpu();
//#define WAITTCNT fintcnt();
sleep_enable();
sei();
uint16_t ovax; //0..1024 = 0...5v
uint8_t msd;
uint8_t lsd;
while(1)
{
frame++;
//H = 1./15734.264 = 63.555 / 2 = 31.7775
for( line = 0; line < 6; line++ )
{ NTSC_LOW; _delay_us(2.3-TIMEOFFSET); NTSC_HI; _delay_us(25-TIMEOFFSET-CLKOFS); }
for( line = 0; line < 6; line++ )
{ NTSC_LOW; _delay_us(27.1-TIMEOFFSET); NTSC_HI; _delay_us(5-TIMEOFFSET-CLKOFS); }
for( line = 0; line < 6; line++ )
{ NTSC_LOW; _delay_us(2.3-TIMEOFFSET); NTSC_HI; _delay_us(25-TIMEOFFSET-CLKOFS); }
for( line = 0; line < 49; line++ )
{
RESETCNT;
NTSC_LOW;
_delay_us(4.7-TIMEOFFSET);
NTSC_HI;
//Do whatever you want.
//sprintf( stdsr, "%d", frame );
switch (line)
{
case 0:
NumToText( stdsr+4, frame );
break;
case 1:
ovax = ADC;
ovax = ovax * 49 + (ovax>>1);
ovax/=10;
break;
case 2:
NumToText( stdsr+24, ovax/1000 );
stdsr[27] = '.';
break;
case 5:
NumToText4( stdsr+27, ovax );
stdsr[27] = '.';
break;
}
WAITTCNT;
//_delay_us(58.8-TIMEOFFSET-CLKOFS);
}
for( line = 0; line < 2; line++ )
{
RESETCNT;
NTSC_LOW;
_delay_us(4.7-TIMEOFFSET);
NTSC_HI;
WAITTCNT;
}
for( line = 0; line < 230; line++ )
{
RESETCNT;
NTSC_LOW; _delay_us(4.7-TIMEOFFSET);
NTSC_HI; _delay_us(8-TIMEOFFSET-CLKOFS);
//#define LINETEST
#ifdef LINETEST
NTSC_VH; _delay_us(8-TIMEOFFSET-CLKOFS);
NTSC_HI; _delay_us(44.5);
#else
ctll = line>>2;
for( k = 0; k < 8; k++ )
{
// draw the character, one pixel at a time
uint8_t ch = pgm_read_byte( &font_8x8_data[(stdsr[k+((ctll>>3)<<3)]<<3)] + (ctll&0x07) );
for( i = 0; i < 8; i++ )
{
if( (ch&1) ) //if pixel is dark...
{
NTSC_VH;
}
else
{
NTSC_HI; // pixel is lit
NOOP;
}
ch>>=1;
NOOP; NOOP; NOOP; NOOP;
}
NTSC_HI;
}
NTSC_HI; //_delay_us(4.7-TIMEOFFSET-CLKOFS);
WAITTCNT;
#endif
// NTSC_HI; _delay_us(46-TIMEOFFSET-CLKOFS);
// NTSC_VH; _delay_us(32-TIMEOFFSET-CLKOFS);
// NTSC_HI; _delay_us(19.8-TIMEOFFSET-CLKOFS);
}
}
return 0;
}