英锐恩单片机论坛,Microchip单片机,模拟器件,接口电路,麦肯单片机,单片机应用交流

标题: Pico OSD, a PIC video superimposer [打印本页]

作者: star    时间: 2012-8-21 15:15
标题: Pico OSD, a PIC video superimposer
本帖最后由 star 于 2012-8-21 15:17 编辑

/*

***************************************************************
****************
* pico OSD : simple PIC OSD PAL video superimposer

***************************************************************
****************
*
* This program shows how to superimpose a text on a PAL composite video signal
* with a PIC and only 4 resistors.
*
* source code for mikro C compiler V7.0.0.3
* feel free to use this code at your own risks
*
* target : PIC12F683 @25MHz
* HS clock, no watchdog.
*
*
*
*

***************************************************************
****************
*/
#include        "built_in.h"
#include        "fonts.h"
/*************************
* CONSTANTS DEFINITIONS
*************************/
   /*
* CVREF = (VR<3:0>/24) × VDD
* PAL CLIP LEVEL : 0.625 V
*/
#define CLIP_VOLTAGE    625             // in mV
#define CLIP_LEVEL      (CLIP_VOLTAGE * 24 / 5000)    // for VR bits CMCON<3:0>
#define OUT             GPIO.F2         // video output
#define HSYMBOLS        11              // number of horizontal symbols
#define FONTH           7               // pixel font height
#define T0FREQ          (Clock_kHz() * 1000 / 4)                // number of TMR0 ticks
in one second
#define T028us          (unsigned char)(T0FREQ * 0.000028)      // number of TMR0
ticks in 28 µs
/************************
* PSEUDO FUNCTIONS
************************/
/*
* this macro definition sets message display from line l, color c (1=white, 0=black),
font size s
*/
#define setMsg(l, c, s) vStart = l ; vStop = vStart + FONTH * s ; lHeight = s ; OUT = c
/*
* set output depending on bit number x of the current position indexed to by FSR
* Note : if you use a 20 Mhz crystal instead of a 25 Mhz crystal, remove NOP
*/
#define SETPIXEL(x)     asm { BTFSC     INDF, x         ; skip next intruction if bit x is
set                  }                         asm { BCF       TRISIO, 2       ; set GP2 as output and
superimpose pixel               }                         asm { NOP                       ; no operation
(enlarges pixel)                         }                         asm { BSF       TRISIO, 2       ; set
GP2 as high Z input (no pixel superimposed)       }
/*
* write the 5 bits of the current character in the current line,
* then increment FSR to point to the next character
*/
#define WRITECHAR()             SETPIXEL(0)                                     SETPIXEL(1)         
                            SETPIXEL(2)                                     SETPIXEL(3)                           
          SETPIXEL(4)                                     FSR++
/***********************
* VARIABLES DEFINITIONS
***********************/
   /*
* demo message to be scrolled
*/
const
   unsigned
   char
   scroll_msg[]
   =
   "Scroll text : pico OSD is scrolling this very long message
on your screen, and then will rewind it very fast. Ready ? Now !"
   ;
unsigned
   char
   line
   =
   0
   ;
   // current line number
unsigned
   char
   ctrLine
   =
   0
   ;
   // counter of line to be repeated (to make big sized fonts)
unsigned
   char
   bm[FONTH][HSYMBOLS]
   absolute
   0x23
   ;
   // bitmap to be superimposed to video
unsigned
   char
   display
   absolute
   0xa0
   ;
   // address of data to be displayed, ensure it is in the
same memory bank as TRISIO
unsigned
   char
   msg[HSYMBOLS
   +
   1]
   ;
   // dynamic string to be displayed
volatile
   unsigned
   char
   vStart
   =
   255
   absolute
   0x20,
   // vertical start : first line to be superimposed
   vStop
   absolute
   0x21,
   // vertical stop : last line to be superimposed
   lHeight
   absolute
   0x22
   ;
   // line height : number of time the same line must be
displayed
unsigned
   int
   frm
   ;
   // frame counter
unsigned
   char
   sec
   =
   0,
   // RTC seconds,
   mn
   =
   0,
   // minutes,
   hours
   =
   0
   ;
   // hours
/****************************
* Interrupt Service routine
****************************/
/*
* since no other interrupts but CMIE are enabled, no need to check this flag.
*/
void
   interrupt()
   {
   if(CMCON0.COUT)
   // if comparator output changed to high
   {
   if((line
   >=
   vStart)
   &&
   (line
   <
   vStop))
   // if we are in display window
   {
   FSR
   =
   display
   ;
   // load FSR with current bitmap address

   WRITECHAR()
   ;
   // set character pixels
   WRITECHAR()
   ;
   WRITECHAR()
   ;
   WRITECHAR()
   ;
   WRITECHAR()
   ;
   WRITECHAR()
   ;
   WRITECHAR()
   ;
   WRITECHAR()
   ;
   WRITECHAR()
   ;
   WRITECHAR()
   ;
   WRITECHAR()
   ;

   ctrLine++
   ;
   // increment same line counter
   if(ctrLine
   ==
   lHeight)
   // do we have to change ?
   {
   display
   +=
   HSYMBOLS
   ;
   // yes, change display location to next bitmap row
   ctrLine
   =
   0
   ;
   // reset counter
   }
   TMR0
   =
   0
   ;
   // keep timer 0 clear to prevent false start of frame
detection
   }
   else
   if(TMR0
   >=
   T028us)
   // if, check low pulse duration
   {
   line
   =
   0
   ;
   // we are in a new frame sync, reset line counter
   ctrLine
   =
   0
   ;
   // reset same line counter
   display
   =
   (char)bm
   ;
   // points to the bitmap start
   }
   }
   else
   // compatator output changed to low
   {
   TMR0
   =
   0
   ;
   // clear timer 0
   if(line
   <
   254)
   // if we can
   {
   line++
   ;
   // increment line counter (only first 255 lines are used)
   }

   /*
                 * Real Time Clock
                 */
   frm++
   ;
   // increment frames counter
   if(frm
   ==
   625
   *
   25)
   // PAL is made of 25 frames of 625 lines per second
   {
   frm
   =
   0
   ;
   // clear counter
   sec++
   ;
   // increment seconds
   if(sec
   >=
   60)
   // check for seconds rollover
   {
   sec
   =
   0
   ;
   // clear seconds
   mn++
   ;
   // increment minutes
   if(mn
   >=
   60)
   // check for minutes rollover
   {
   mn
   =
   0
   ;
   // clear minutes
   hours++
   ;
   // increment hours
   }
   }
   }
   }
   PIR1.CMIF
   =
   0
   ;
   // clear comparator interrupt flag
   }
   /*
* update display bitmap with character c at column pos
*/
void
   updatechar(unsigned
   char
   c,
   unsigned
   char
   pos)
   {
   unsigned
   char
   py,
   col
   ;

   /*
         * check for under/overflow
         */
   if(c
   <
   32)
   c
   =
   32
   ;
   else
   if(c
   >
   128)
   c
   =
   32
   ;
   else
   c
   -=
   32
   ;
   // control characters under space in ASCII table are not
displayed

   for(col
   =
   0
   ;
   col
   <
   5
   ;
   col++)
   // for each character columns
   {
   unsigned
   char
   fnt
   =
   fonts[c
   *
   5
   +
   col]
   ;
   // get bitmap font
   unsigned
   char
   mask
   =
   1
   <<
   col
   ;
   // build bitmap mask

   for(py
   =
   0
   ;
   py
   <
   FONTH
   ;
   py++)
   // for each character lines
   {
   if(fnt.F0)
   {
   bm[py][pos]
   |=
   mask
   ;
   // set pixel
   }
   else
   {
   bm[py][pos]
   &=
   ~mask
   ;
   // clear pixel
   }
   fnt
   >>=
   1
   ;
   // shift bitmap mask
   }
   }
   }
/*
* update display message with constant string pointed to by m with offset o within
the string
*/
void
   updateMsg(const
   char
   *m,
   unsigned
   char
   o)
   {
   unsigned
   char
   n,
   l,
   c
   ;

   /*
         * get string length
         */
   l
   =
   0
   ;
   while(m[l++])
   ;

   for(n
   =
   0
   ;
   n
   <
   HSYMBOLS
   ;
   n++)
   // for all symbols
   {
   c
   =
   m[o++]
   ;
   // get character
   o
   %=
   l
   ;
   // circularize string
   updateChar(c,
   n)
   ;
   // put character to display bitmap
   }
   }
/*
* 10 ms delay, c times
*/
void
   delay10ms(unsigned
   char
   c)
   {
   do
   {
   Delay_ms(10)
   ;
   }
   while(--c)
   ;
   }
/*
* program entry
*/
void
   main()
   {
   unsigned
   char
   i
   ;
   GPIO
   =
   0b100
   ;
   // GP2 is set to one be default (text is superimposed in
white)
   TRISIO
   =
   0b110
   ;
   // GP1 is video input, GP2 is video output (set to high Z
first)
   CMCON0
   =
   0b10100
   ;
   // comparator module : no output, uses internal voltage
reference
   VRCON
   =
   0b10100000
   |
   CLIP_LEVEL
   ;
   // voltage reference module : inverted output, low level
   ANSEL
   =
   0b10
   ;
   // all pins but GP1 (comparator input) as digital

   OPTION_REG
   =
   0b10001000
   ;
   // no prescaler on TMR0
   PIE1.CMIE
   =
   1
   ;
   // enable comparator interrupt
   INTCON.PEIE
   =
   1
   ;
   // enable peripheral interrupt
   INTCON.GIE
   =
   1
   ;
   // enable global interrupt

   /*
         * init display window
         */
   lHeight
   =
   1
   ;
   vStart
   =
   10
   ;
   vStop
   =
   10
   ;

   /*************************
         * pico OSD demonstration
         *************************/

   /*
         * welcome messages
         */
   updateMsg("Welcome to ",
   0)
   ;
   for(i
   =
   1
   ;
   i
   <
   10
   ;
   i++)
   {
   setMsg(50,
   1,
   i)
   ;
   delay10ms(5)
   ;
   }
   delay10ms(100)
   ;

   updateMsg("  pico OSD ",
   0)
   ;
   setMsg(100,
   1,
   6)
   ;
   delay10ms(100)
   ;

   updateMsg("the tiniest",
   0)
   ;
   setMsg(100,
   1,
   6)
   ;
   delay10ms(100)
   ;

   updateMsg("OSD of the ",
   0)
   ;
   setMsg(100,
   1,
   6)
   ;
   delay10ms(100)
   ;

   updateMsg("WORLD !!!!!",
   0)
   ;
   setMsg(100,
   1,
   6)
   ;
   delay10ms(500)
   ;

   updateMsg(" It can... ",
   0)
   ;
   setMsg(100,
   1,
   6)
   ;
   delay10ms(500)
   ;

   /*
         * move message along vertical axe
         */
   updateMsg(" Move text ",
   0)
   ;
   for(i
   =
   20
   ;
   i
   <
   195
   ;
   i++)
   {
   setMsg(i,
   1,
   6)
   ;
   delay10ms(1)
   ;
   }
   for(
   ;
   i
   >
   20
   ;
   i--)
   {
   setMsg(i,
   1,
   6)
   ;
   delay10ms(1)
   ;
   }
   for(
   ;
   i
   <
   100
   ;
   i++)
   {
   setMsg(i,
   1,
   6)
   ;
   delay10ms(1)
   ;
   }
   delay10ms(100)
   ;

   /*
         * horizontal scroll
         */
   updateMsg(scroll_msg,
   0)
   ;
   delay10ms(200)
   ;
   for(i
   =
   0
   ;
   i
   <
   sizeof(scroll_msg)
   -
   HSYMBOLS
   ;
   i++)
   {
   updateMsg(scroll_msg,
   i)
   ;
   setMsg(100,
   1,
   6)
   ;
   delay10ms(10)
   ;
   }
   delay10ms(50)
   ;
   for(
   ;
   i
   >
   0
   ;
   i--)
   {
   updateMsg(scroll_msg,
   i)
   ;
   setMsg(100,
   1,
   6)
   ;
   delay10ms(3)
   ;
   }
   updateMsg(scroll_msg,
   0)
   ;
   delay10ms(100)
   ;

   /*
         * change text size
         */
   updateMsg("Resize text",
   0)
   ;
   delay10ms(100)
   ;
   for(i
   =
   6
   ;
   i
   <
   20
   ;
   i++)
   {
   setMsg(100,
   1,
   i)
   ;
   delay10ms(10)
   ;
   }
   for(
   ;
   i
   >
   0
   ;
   i--)
   {
   setMsg(100,
   1,
   i)
   ;
   delay10ms(10)
   ;
   }
   for(i
   =
   1
   ;
   i
   <
   6
   ;
   i++)
   {
   setMsg(100,
   1,
   i)
   ;
   delay10ms(10)
   ;
   }
   delay10ms(100)
   ;

   /*
         * change text color
         */
   for(i
   =
   0
   ;
   i
   <
   2
   ;
   i++)
   {
   updateMsg("  In Black ",
   0)
   ;
   setMsg(100,
   0,
   6)
   ;
   delay10ms(100)
   ;

   updateMsg("  Or White ",
   0)
   ;
   setMsg(100,
   1,
   6)
   ;
   delay10ms(100)
   ;
   }

   /*
         * prepare to display run time
         */
   updateMsg("Run time : ",
   0)
   ;
   setMsg(100,
   1,
   6)
   ;
   delay10ms(100)
   ;
   setMsg(40,
   1,
   3)
   ;
   delay10ms(100)
   ;

   updateChar('H',
   2)
   ;
   updateChar('m',
   5)
   ;
   updateChar('i',
   6)
   ;
   updateChar('n',
   7)
   ;
   updateChar('s',
   10)
   ;

   /*
         * update run time clock display
         */
   for(;;)
   {
   updateChar(hours
   /
   10
   +
   '0',
   0)
   ;
   updateChar(hours
   %
   10
   +
   '0',
   1)
   ;

   updateChar(mn
   /
   10
   +
   '0',
   3)
   ;
   updateChar(mn
   %
   10
   +
   '0',
   4)
   ;

   updateChar(sec
   /
   10
   +
   '0',
   8)
   ;
   updateChar(sec
   %
   10
   +
   '0',
   9)
   ;
   }
   }






欢迎光临 英锐恩单片机论坛,Microchip单片机,模拟器件,接口电路,麦肯单片机,单片机应用交流 (http://enroobbs.com/) Powered by Discuz! X3.2