videochargen/main.c

92 lines
2.0 KiB
C
Raw Normal View History

/**
* @file main.c
* @author giomba@glgprograms.it
* @brief OSDY main.
*
* @copyright Copyright RetrOfficina GLG Programs (c) 2022
*
* Video image generator superimposition for analog PAL signals,
* with Atmega328, for your retro OSD titles.
*
*/
2021-07-03 13:02:01 +00:00
#include "const.h"
#include <avr/interrupt.h>
#include <avr/io.h>
#include <string.h>
2021-07-03 13:02:01 +00:00
volatile uint16_t frame = 0;
volatile uint16_t line = 0xfe;
volatile uint8_t image = 0xff;
2022-11-04 19:51:43 +00:00
// horizontal and vertical position
// (and current increments)
// of bouncing sprite
2022-11-03 19:51:18 +00:00
volatile uint8_t vpos = 0;
volatile uint16_t hpos = 0;
2022-11-03 19:51:18 +00:00
volatile int8_t vinc = +1;
volatile int8_t hinc = +1;
2022-11-04 19:51:43 +00:00
// vertical sync interrupt
2022-11-03 19:51:18 +00:00
void int_vertical_sync_s(void);
ISR(INT0_vect) {
2022-11-04 19:51:43 +00:00
// count frames
2022-11-03 19:51:18 +00:00
frame += 1;
2022-11-04 19:51:43 +00:00
// move sprite
2022-11-03 19:51:18 +00:00
vpos += vinc;
hpos += hinc;
2022-11-04 19:51:43 +00:00
// invert bouncing direction
2022-11-03 19:51:18 +00:00
if (vpos == 0)
vinc = +1;
2022-11-04 20:02:53 +00:00
if (vpos == FRAME_LINE_HEIGHT - SPRITE_LINE_HEIGHT)
2022-11-03 19:51:18 +00:00
vinc = -1;
2022-11-04 20:02:53 +00:00
if (hpos == BACK_PORCH_SYSCLOCK_OFFSET)
2022-11-03 19:51:18 +00:00
hinc = +1;
2022-11-04 20:02:53 +00:00
if (hpos == FRAME_SYSCLOCK_WIDTH - SPRITE_SYSCLOCK_WIDTH -
FRONT_PORCH_SYSCLOCK_OFFSET - HSYNC_SYSCLOCK_TUNE)
2022-11-03 19:51:18 +00:00
hinc = -1;
int_vertical_sync_s();
}
2022-11-03 19:51:18 +00:00
2022-11-04 19:51:43 +00:00
// horizontal sync interrupt
2022-11-03 19:51:18 +00:00
void int_horizontal_sync_s(void);
ISR(INT1_vect) {
2022-11-04 19:51:43 +00:00
// count lines
2022-11-03 19:51:18 +00:00
line += 1;
2022-11-04 19:51:43 +00:00
// we are past the last line of the sprite
2022-11-04 20:02:53 +00:00
if (line >= vpos + SPRITE_LINE_HEIGHT)
2022-11-03 19:51:18 +00:00
return;
if (line >= vpos)
int_horizontal_sync_s();
}
2022-11-03 19:51:18 +00:00
ISR(TIMER1_COMPA_vect, ISR_NAKED) {
2022-11-04 19:51:43 +00:00
// end-of back porch timer interrupt
asm("jmp int_timer_1");
}
2021-07-03 13:02:01 +00:00
// external assembly main loop
void main_asm(void);
int main() {
// port B, pin 4 and 5 as output, others as input
DDRB |= 0x30;
2021-07-03 13:44:01 +00:00
// set interrupt vectors at address 0x0, not bootloader
// timing is important, see atmel datasheet
_SFR_IO8(MCUCR) = (1 << IVCE);
_SFR_IO8(MCUCR) = 0;
EICRA = 0x0a; // external interrupt 0 and 1, falling edge
EIMSK = 0x03; // external interrupt 0 and 1, mask enable
TCCR1A = 0x00; // don't connect output pins to timer, CTC[1:0] mode
TCCR1B = 0x09; // CTC[3:2] mode, no prescaler
main_asm();
}