• メインページ
  • データ構造
  • ファイル
  • ファイル一覧
  • グローバル

OpenSSM/libvideo.c

説明を見る。
00001 /**************************************************************************************************
00002     Title           : NTSC Composit VIDEO Driver for PIC24F Series
00003     Programmer      : Yosuke FURUSAWA
00004     Copyright       : Copyright (C)2010 Yosuke FURUSAWA.
00005     License         : 4-clause BSD License
00006     Since           : 2010/04/28
00007 
00008     Filename        : libvideo.c
00009     Last up date    : 2010/08/13
00010     Kanji-Code      : Shift-JIS
00011     TAB Space       : 4
00012 
00013     Note            : 画面両端の 2pxは、使えない
00014 **************************************************************************************************/
00015 
00016 
00017 /*=================================================================================================
00018 ヘッダファイルをインクロード
00019 =================================================================================================*/
00020 #include <p24FJ64GA002.h>
00021 
00022 #include "types.h"
00023 #include "table.h"
00024 
00025 #include "librtc.h"
00026 #include "libfontx2.h"
00027 #include "libvideo.h"
00028 
00029 
00030 /*=================================================================================================
00031 マクロ定義
00032 =================================================================================================*/
00033 #define abs(a)                      (((a)>0) ? (a) : -(a))
00034 
00035 /* 同期信号出力 */
00036 #define NTSC_SYNC                   LATBbits.LATB12
00037 #define NTSC_VIDEO                  LATBbits.LATB13
00038 
00039 /* NTSC-M 標準設定 */
00040 #define NTSC_LINE                   263         /* インターレース 525本の半分 */
00041 #define NTSC_LINE_SYNC              13          /* 垂直帰線区間. 標準11H, ノンインターレースとして +2 */
00042 #define NTSC_LINE_SPACE_TOP         29          /* 上部の空白部分 */
00043 
00044 /* パルスの標準時間 @ Fcy = 16MHz */
00045 #define NTSC_DEFAULT_FCY            cpu_fcy[0]
00046 #define NTSC_HORIZON_PULSE          1015
00047 #define NTSC_SERRATION_PULSE        936
00048 #define NTSC_EQUALIZING_PULSE       70
00049 #define NTSC_LEFT_SPACE             220
00050 #define NTSC_VIDEO_WIDTH            256
00051 
00052 
00053 /*=================================================================================================
00054 構造体
00055 =================================================================================================*/
00056 
00057 
00058 /*=================================================================================================
00059 グローバル変数
00060 =================================================================================================*/
00061 /* VRAM */
00062 static unsigned int __attribute__((far)) video_memory[ NTSC_VRAM_SIZE / 2 ];
00063 
00064 /* ドライバ用 */
00065 NTSC_T ntsc = {
00066     video_memory,
00067     0,
00068 
00069     {
00070         video_memory,
00071         NTSC_LINE,
00072         NTSC_LINE_SYNC,
00073         NTSC_LINE_SYNC + NTSC_LINE_SPACE_TOP,
00074         NTSC_LINE_SYNC + NTSC_LINE_SPACE_TOP + NTSC_HEIGHT,
00075         NTSC_HORIZON_PULSE,
00076         NTSC_SERRATION_PULSE,
00077         NTSC_EQUALIZING_PULSE,
00078         NTSC_LEFT_SPACE,
00079         NTSC_WIDTH,
00080         0x0000,
00081         0x0000,
00082         0x0000,
00083     },
00084 
00085     {
00086         video_memory,
00087         NTSC_LINE,
00088         NTSC_LINE_SYNC,
00089         NTSC_LINE_SYNC + NTSC_LINE_SPACE_TOP + 10,
00090         NTSC_LINE_SYNC + NTSC_LINE_SPACE_TOP + 10 + NTSC_HEIGHT,
00091         NTSC_HORIZON_PULSE,
00092         NTSC_SERRATION_PULSE,
00093         NTSC_EQUALIZING_PULSE,
00094         NTSC_LEFT_SPACE,
00095         NTSC_WIDTH,
00096         0x0000,
00097         0x0000,
00098         0x0000,
00099     },
00100 
00101 };
00102 
00103 /* API用 */
00104 VIDEO_T video;
00105 
00106 
00107 /**************************************************************************************************
00108 プロトタイプ宣言
00109 **************************************************************************************************/
00110 inline static void VIDEO_init_superimpose(void);
00111 
00112 
00113 /**************************************************************************************************
00114 初期化
00115 **************************************************************************************************/
00116 void VIDEO_init(void)
00117 {
00118     /* 変数初期化 */
00119     video.cx = 0;
00120     video.cy = 0;
00121     VIDEO_vram_clear(0x0000);
00122 
00123 
00124     /* モニタ出力用の初期化 */
00125     VIDEO_init_clock();
00126     RPOR6bits.RP13R = 7;
00127 
00128     /*           FEDBCA9876543210 */
00129     SPI1CON1 = 0b0000010000110111;
00130     SPI1CON2 = 0b0000000000000000;
00131     SPI1STAT = 0b1000000000000000;
00132     IPC2bits.SPI1IP = 7;
00133     IEC0bits.SPI1IE = 1;
00134     IFS0bits.SPI1IF = 0;
00135     IPC0bits.OC1IP = 7;
00136     IEC0bits.OC1IE = 1;
00137     IFS0bits.OC1IF = 0;
00138     IPC1bits.OC2IP = 7;
00139     IEC0bits.OC2IE = 1;
00140     IFS0bits.OC2IF = 0;
00141 
00142     PR2 = ntsc.monitor.horizon_pulse;
00143     TMR2 = 0x0000;
00144     IPC1bits.T2IP = 7;
00145     IEC0bits.T2IE = 1;
00146     IFS0bits.T2IF = 0;
00147 
00148     /*        FEDBCA9876543210 */
00149     T2CON = 0b1000000000000000;
00150 
00151     /* スーパーインポーズ用の初期化 */
00152     VIDEO_init_superimpose();
00153 
00154     return;
00155 }
00156 
00157 inline static void VIDEO_init_superimpose(void)
00158 {
00159     RPOR7bits.RP15R = 10;
00160 
00161     /* VSYNC割り込みの有効化 */
00162     RPINR0bits.INT1R = 10;          /* RP10 INT1 */
00163     INTCON2bits.INT1EP = 1;         /* 立ち下がり */
00164     IPC5bits.INT1IP = 6;
00165     IEC1bits.INT1IE = 1;
00166     IFS1bits.INT1IF = 0;
00167 
00168     /* HSYNC割り込みの有効化 */
00169     RPINR1bits.INT2R = 11;          /* RP11 INT2 */
00170     INTCON2bits.INT2EP = 0;         /* 立ち上がり */
00171     IPC7bits.INT2IP = 6;
00172     IEC1bits.INT2IE = 1;
00173     IFS1bits.INT2IF = 0;
00174 
00175     /* ビデオ出力用 */
00176     /*           FEDBCA9876543210 */
00177     SPI2CON1 = 0b0000010000110111;
00178     SPI2CON2 = 0b0000000000000000;
00179     SPI2STAT = 0b1000000000000000;
00180     IPC8bits.SPI2IP = 6;
00181     IEC2bits.SPI2IE = 1;
00182     IFS2bits.SPI2IF = 0;
00183 
00184     IPC6bits.OC3IP = 6;
00185     IEC1bits.OC3IE = 0;
00186     IFS1bits.OC3IF = 0;
00187 
00188     PR3  = 0xffff;
00189     TMR3 = 0x0000;
00190     T3CON = 0x8000;
00191     IPC2bits.T3IP   = 6;
00192     IEC0bits.T3IE   = 1;
00193     IFS0bits.T3IF   = 0;
00194 
00195     return;
00196 }
00197 
00198 
00199 /**************************************************************************************************
00200 割り込み周期の初期化
00201 **************************************************************************************************/
00202 void VIDEO_init_clock(void)
00203 {
00204     ntsc.monitor.horizon_pulse      = (double)NTSC_HORIZON_PULSE    * ((double)cpu_fcy[ OSCTUN ] / (double)NTSC_DEFAULT_FCY);
00205     ntsc.monitor.serration_pulse    = (double)NTSC_SERRATION_PULSE  * ((double)cpu_fcy[ OSCTUN ] / (double)NTSC_DEFAULT_FCY);
00206     ntsc.monitor.equalizing_pulse   = (double)NTSC_EQUALIZING_PULSE * ((double)cpu_fcy[ OSCTUN ] / (double)NTSC_DEFAULT_FCY);
00207     ntsc.monitor.left_space         = (double)NTSC_LEFT_SPACE       * ((double)cpu_fcy[ OSCTUN ] / (double)NTSC_DEFAULT_FCY);
00208     ntsc.monitor.video_width        = (double)NTSC_VIDEO_WIDTH      * ((double)cpu_fcy[ OSCTUN ] / (double)NTSC_DEFAULT_FCY);
00209 
00210     if(ntsc.monitor.video_width > NTSC_WIDTH)   ntsc.monitor.video_width = NTSC_WIDTH;
00211     ntsc.monitor.video_width = ntsc.monitor.video_width >> 4;
00212 
00213     ntsc.superimpose.left_space     = (double)108                   * ((double)cpu_fcy[ OSCTUN ] / (double)NTSC_DEFAULT_FCY);
00214     ntsc.superimpose.video_width    = ntsc.monitor.video_width;
00215 
00216     return;
00217 }
00218 
00219 
00220 /**************************************************************************************************
00221 モニター出力用 NTSC信号処理関数
00222 **************************************************************************************************/
00223 void __attribute__((interrupt, no_auto_psv, shadow)) _T2Interrupt(void)
00224 {
00225     IFS0bits.T2IF = 0;
00226     NTSC_SYNC = 0;
00227     ntsc.monitor.vsync++;
00228 
00229     /* 切り込みパルス */
00230     if(ntsc.monitor.vsync < ntsc.monitor.line_sync){
00231         OC1R = ntsc.monitor.serration_pulse;
00232         OC1CON = 0x0001;
00233         ntsc.output = 0;
00234 
00235     /* 上部空白 */
00236     } else if(ntsc.monitor.vsync < ntsc.monitor.line_space_top){
00237         OC1R = ntsc.monitor.equalizing_pulse;
00238         OC1CON = 0x0001;
00239 
00240     /* 映像出力 */
00241     } else if(ntsc.monitor.vsync < ntsc.monitor.line_video){
00242         OC1R = ntsc.monitor.equalizing_pulse;
00243         OC1CON = 0x0001;
00244         OC2R = ntsc.monitor.left_space;
00245         OC2CON = 0x0001;
00246 
00247     /* 下部空白 */
00248     } else if(ntsc.monitor.vsync < ntsc.monitor.line - 1){
00249         OC1R = ntsc.monitor.equalizing_pulse;
00250         OC1CON = 0x0001;
00251 
00252     } else {
00253         OC1R = ntsc.monitor.equalizing_pulse;
00254         OC1CON = 0x0001;
00255         PR2 = ntsc.monitor.horizon_pulse;
00256         ntsc.monitor.vsync = 0;
00257         ntsc.monitor.vram = ntsc.vram;
00258 
00259         /* モニタ出力のときはインポーズ用信号を Highに固定し、LM1881のノイズ耐性を上げる */
00260         RPOR7bits.RP15R = 0;
00261         LATBbits.LATB15 = 1;
00262         ntsc.output = 0;
00263 
00264     }
00265 
00266     return;
00267 }
00268 
00269 void __attribute__((interrupt, no_auto_psv, shadow)) _OC1Interrupt(void)
00270 {
00271     IFS0bits.OC1IF = 0;
00272     NTSC_SYNC = 1;
00273     return;
00274 }
00275 
00276 
00277 void __attribute__((interrupt, no_auto_psv, shadow)) _OC2Interrupt(void)
00278 {
00279     unsigned int dummy;
00280 
00281     IFS0bits.OC2IF = 0;
00282 
00283     SPI1BUF = *ntsc.monitor.vram++;
00284     ntsc.monitor.hsync = 2;
00285     while(SPI1STATbits.SPITBF);
00286     dummy = SPI1BUF;
00287     SPI1BUF = *ntsc.monitor.vram++;
00288     return;
00289 }
00290 
00291 void __attribute__((interrupt, no_auto_psv, shadow)) _SPI1Interrupt(void)
00292 {
00293     unsigned int dummy;
00294 
00295     IFS0bits.SPI1IF = 0;
00296 
00297     if(ntsc.monitor.hsync == 0){
00298         SPI1BUF = (*ntsc.monitor.vram++) & 0x7fff;                  /* 左端を描画しない */
00299         ntsc.monitor.hsync++;
00300 
00301     } else if(ntsc.monitor.hsync < ntsc.monitor.video_width - 1){
00302         SPI1BUF = *ntsc.monitor.vram++;
00303         ntsc.monitor.hsync++;
00304 
00305     } else if(ntsc.monitor.hsync < ntsc.monitor.video_width){
00306         SPI1BUF = (*ntsc.monitor.vram++) & 0xfffe;                  /* 右端を描画しない */
00307         ntsc.monitor.hsync++;
00308 
00309     } else {
00310         for(;ntsc.monitor.hsync < (NTSC_WIDTH >> 4); ntsc.monitor.hsync++){
00311             ntsc.monitor.vram++;
00312         }
00313     }
00314 
00315     dummy = SPI1BUF;
00316     return;
00317 }
00318 
00319 
00320 /**************************************************************************************************
00321 スーパーインポーズ用 NTSC信号処理関数 (タイミングがシビアすぎて、これ以上の調整不可...)
00322 **************************************************************************************************/
00323 void __attribute__((interrupt, auto_psv)) _INT1Interrupt(void)
00324 {
00325     unsigned int dummy;
00326 
00327     IFS1bits.INT1IF = 0;
00328 
00329     /* モニタ出力を止める */
00330     IEC0bits.T2IE = 0;
00331 
00332     /* 原因はよく分からないが、初期化すると面白いほど同期が取れる... */
00333     VIDEO_init_superimpose();
00334     ntsc.output = 1;
00335 
00336     dummy = SPI2BUF;
00337     ntsc.superimpose.vram  = ntsc.vram;
00338     ntsc.superimpose.vsync = 0;
00339 
00340     return;
00341 }
00342 
00343 
00344 void __attribute__((interrupt, auto_psv)) _INT2Interrupt(void)
00345 {
00346     unsigned int dummy;
00347 
00348     IFS1bits.INT2IF = 0;
00349 
00350     ntsc.superimpose.vsync++;
00351 
00352     /* 上部空白 */
00353     if(ntsc.superimpose.vsync < ntsc.superimpose.line_space_top){
00354         /* 何もしない */
00355 
00356     /* 映像出力 */
00357     } else if (ntsc.superimpose.vsync < ntsc.superimpose.line_video){
00358         TMR3 = 0x0000;
00359         OC3R = ntsc.superimpose.left_space;
00360         OC3CON = 0b0000000000001001;
00361         IEC1bits.OC3IE  = 1;
00362         dummy = SPI2BUF;
00363 
00364     } else {
00365         IEC1bits.INT2IE = 0;
00366         dummy = SPI2BUF;
00367     }
00368 
00369     return;
00370 }
00371 
00372 void __attribute__((interrupt, auto_psv)) _OC3Interrupt(void)
00373 {
00374     unsigned int dummy;
00375 
00376     IFS1bits.OC3IF = 0;
00377 
00378     SPI2BUF = *ntsc.superimpose.vram++;
00379     ntsc.superimpose.hsync = 2;
00380     while(SPI2STATbits.SPITBF);
00381     dummy = SPI2BUF;
00382     SPI2BUF = *ntsc.superimpose.vram++;
00383 
00384     IEC1bits.OC3IE = 0;
00385     return;
00386 }
00387 
00388 void __attribute__((interrupt, no_auto_psv)) _SPI2Interrupt(void)
00389 {
00390     unsigned int dummy;
00391 
00392     IFS2bits.SPI2IF = 0;
00393 
00394     if(ntsc.superimpose.hsync == 0){
00395         SPI2BUF = (*ntsc.superimpose.vram++) & 0x7fff;              /* 左端を描画しない */
00396         ntsc.superimpose.hsync++;
00397 
00398     } else if(ntsc.superimpose.hsync < ntsc.superimpose.video_width - 1){
00399         SPI2BUF = *ntsc.superimpose.vram++;
00400         ntsc.superimpose.hsync++;
00401 
00402     } else if(ntsc.superimpose.hsync < ntsc.superimpose.video_width){
00403         SPI2BUF = (*ntsc.superimpose.vram++) & 0xfffe;              /* 右端を描画しない */
00404         ntsc.superimpose.hsync++;
00405 
00406     } else {
00407         for(;ntsc.superimpose.hsync < (NTSC_WIDTH >> 4); ntsc.superimpose.hsync++){
00408             ntsc.superimpose.vram++;
00409         }
00410     }
00411 
00412     dummy = SPI2BUF;
00413     return;
00414 }
00415 
00416 void __attribute__((interrupt, auto_psv)) _T3Interrupt(void)
00417 {
00418     /* スーパーインポーズ用の外部ビデオ信号がないときに実行される */
00419     IFS0bits.T3IF = 0;
00420 
00421     IEC0bits.T2IE = 1;
00422     IEC0bits.T3IE = 0;
00423     IEC1bits.INT2IE = 0;
00424 
00425     ntsc.output = 0;
00426 
00427     return;
00428 }
00429 
00430 
00431 
00432 /**************************************************************************************************
00433 VRAMの初期化. 16ビット横のパターンで全体を設定する
00434 **************************************************************************************************/
00435 void VIDEO_vram_clear(unsigned int pattern)
00436 {
00437     unsigned int i, *vram;
00438 
00439     vram = ntsc.vram;
00440 
00441     for(i = 0; i < (NTSC_VRAM_SIZE >> 1); i++){
00442         *vram = pattern;
00443         vram++;
00444     }
00445 
00446     return;
00447 }
00448 
00449 
00450 /**************************************************************************************************
00451 出力先を得る
00452 **************************************************************************************************/
00453 unsigned char VIDEO_get_output(void)
00454 {
00455     return(ntsc.output);
00456 }
00457 
00458 
00459 /**************************************************************************************************
00460 点の有無を得る
00461 **************************************************************************************************/
00462 unsigned int VIDEO_get_point(unsigned int x, unsigned int y)
00463 {
00464     const unsigned int table[] = {
00465     /*    FEDCBA9876543210 */
00466         0b1000000000000000,     /* 0 */
00467         0b0100000000000000,     /* 1 */
00468         0b0010000000000000,     /* 2 */
00469         0b0001000000000000,     /* 3 */
00470         0b0000100000000000,     /* 4 */
00471         0b0000010000000000,     /* 5 */
00472         0b0000001000000000,     /* 6 */
00473         0b0000000100000000,     /* 7 */
00474         0b0000000010000000,     /* 8 */
00475         0b0000000001000000,     /* 9 */
00476         0b0000000000100000,     /* a */
00477         0b0000000000010000,     /* b */
00478         0b0000000000001000,     /* c */
00479         0b0000000000000100,     /* d */
00480         0b0000000000000010,     /* e */
00481         0b0000000000000001,     /* f */
00482     };
00483 
00484 #ifndef VIDEO_FAST
00485     if(x >= NTSC_WIDTH)     x = NTSC_WIDTH  - 1;
00486     if(y >= NTSC_HEIGHT)    y = NTSC_HEIGHT - 1;
00487 #endif
00488 
00489 #ifdef VIDEO_MIRROR
00490     x = (NTSC_WIDTH - 1) - x;
00491 #endif
00492 
00493     return(ntsc.vram[ (y << 4) + (x >> 4) ] & table[ (x & 0x0f) ] ? 1 : 0);
00494 }
00495 
00496 
00497 /**************************************************************************************************
00498 点を描く / 消す
00499 **************************************************************************************************/
00500 inline void VIDEO_point(unsigned int x, unsigned int y)
00501 {
00502 #ifndef VIDEO_FAST
00503     if(x >= NTSC_WIDTH)     x = NTSC_WIDTH  - 1;
00504     if(y >= NTSC_HEIGHT)    y = NTSC_HEIGHT - 1;
00505 #endif
00506 
00507 #ifdef VIDEO_MIRROR
00508     x = (NTSC_WIDTH - 1) - x;
00509 #endif
00510 
00511     ntsc.vram[ ((NTSC_HEIGHT - 1 - y) << 4) + (x >> 4) ] |=  (0x8000 >> (x & 0x0f));
00512     return;
00513 }
00514 inline void VIDEO_point_(unsigned int x, unsigned int y)
00515 {
00516 #ifndef VIDEO_FAST
00517     if(x >= NTSC_WIDTH)     x = NTSC_WIDTH  - 1;
00518     if(y >= NTSC_HEIGHT)    y = NTSC_HEIGHT - 1;
00519 #endif
00520 
00521 #ifdef VIDEO_MIRROR
00522     x = (NTSC_WIDTH - 1) - x;
00523 #endif
00524 
00525     ntsc.vram[ ((NTSC_HEIGHT - 1 - y) << 4) + (x >> 4) ] &= ‾(0x8000 >> (x & 0x0f));
00526     return;
00527 }
00528 
00529 
00530 /**************************************************************************************************
00531 直線を描く / 消す (Bresenham style)
00532 **************************************************************************************************/
00533 void VIDEO_line(int x0, int y0, int x1, int y1)
00534 {
00535     int steep, t;
00536     int deltax, deltay, error;
00537     int x, y;
00538     int ystep;
00539 
00540 #ifndef VIDEO_FAST
00541     if(x0 < 0)              x0 = 0;
00542     if(x0 >= NTSC_WIDTH)    x0 = NTSC_WIDTH  - 1;
00543     if(x1 < 0)              x1 = 0;
00544     if(x1 >= NTSC_WIDTH)    x1 = NTSC_WIDTH  - 1;
00545     if(y0 < 0)              y0 = 0;
00546     if(y0 >= NTSC_HEIGHT)   y0 = NTSC_HEIGHT - 1;
00547     if(y1 < 0)              y1 = 0;
00548     if(y1 >= NTSC_HEIGHT)   y1 = NTSC_HEIGHT - 1;
00549 #endif
00550 
00551     steep = (abs(y1 - y0) > abs(x1 - x0));
00552 
00553     if(steep){
00554         t = x0; x0 = y0; y0 = t;
00555         t = x1; x1 = y1; y1 = t;
00556     }
00557     if(x0 > x1) {
00558         t = x0; x0 = x1; x1 = t;
00559         t = y0; y0 = y1; y1 = t;
00560     }
00561 
00562     deltax = x1 - x0;
00563     deltay = abs(y1 - y0);
00564     error = 0;
00565     y = y0;
00566 
00567     if(y0 < y1) ystep =  1;
00568     else        ystep = -1;
00569 
00570     if(steep){
00571         for(x = x0; x < x1; x++) {
00572             VIDEO_point(y,x);
00573 
00574             error += deltay;
00575 
00576             if((error << 1) >= deltax){
00577                 y     += ystep;
00578                 error -= deltax;
00579             }
00580         }
00581     } else {
00582         for(x = x0; x < x1; x++) {
00583             VIDEO_point(x,y);
00584 
00585             error += deltay;
00586 
00587             if((error << 1) >= deltax){
00588                 y     += ystep;
00589                 error -= deltax;
00590             }
00591         }
00592     }
00593 
00594     return;
00595 }
00596 
00597 void VIDEO_line_(int x0, int y0, int x1, int y1)
00598 {
00599     int steep, t;
00600     int deltax, deltay, error;
00601     int x, y;
00602     int ystep;
00603 
00604 #ifndef VIDEO_FAST
00605     if(x0 < 0)              x0 = 0;
00606     if(x0 >= NTSC_WIDTH)    x0 = NTSC_WIDTH  - 1;
00607     if(x1 < 0)              x1 = 0;
00608     if(x1 >= NTSC_WIDTH)    x1 = NTSC_WIDTH  - 1;
00609     if(y0 < 0)              y0 = 0;
00610     if(y0 >= NTSC_HEIGHT)   y0 = NTSC_HEIGHT - 1;
00611     if(y1 < 0)              y1 = 0;
00612     if(y1 >= NTSC_HEIGHT)   y1 = NTSC_HEIGHT - 1;
00613 #endif
00614 
00615     steep = (abs(y1 - y0) > abs(x1 - x0));
00616 
00617     if(steep){
00618         t = x0; x0 = y0; y0 = t;
00619         t = x1; x1 = y1; y1 = t;
00620     }
00621     if(x0 > x1) {
00622         t = x0; x0 = x1; x1 = t;
00623         t = y0; y0 = y1; y1 = t;
00624     }
00625 
00626     deltax = x1 - x0;
00627     deltay = abs(y1 - y0);
00628     error = 0;
00629     y = y0;
00630 
00631     if(y0 < y1) ystep =  1;
00632     else        ystep = -1;
00633 
00634     if(steep){
00635         for(x = x0; x < x1; x++) {
00636             VIDEO_point_(y,x);
00637 
00638             error += deltay;
00639 
00640             if((error << 1) >= deltax){
00641                 y     += ystep;
00642                 error -= deltax;
00643             }
00644         }
00645     } else {
00646         for(x = x0; x < x1; x++) {
00647             VIDEO_point_(x,y);
00648 
00649             error += deltay;
00650 
00651             if((error << 1) >= deltax){
00652                 y     += ystep;
00653                 error -= deltax;
00654             }
00655         }
00656     }
00657 
00658     return;
00659 }
00660 
00661 
00662 /**************************************************************************************************
00663 円または孤を描く / 消す
00664 **************************************************************************************************/
00665 void VIDEO_arc (unsigned int x, unsigned int y, unsigned int r, unsigned int start, unsigned int end)
00666 {
00667     unsigned int deg;
00668 
00669 #ifndef VIDEO_FAST
00670     if(start > end){
00671         deg   = end;
00672         end   = start;
00673         start = deg;
00674     }
00675 #endif
00676 
00677     for(deg = start; deg < end; deg++){
00678         VIDEO_point (x + (double)r * tcos[deg], y + (double)r * tsin[deg]);
00679     }
00680 
00681     return;
00682 }
00683 
00684 void VIDEO_arc_(unsigned int x, unsigned int y, unsigned int r, unsigned int start, unsigned int end)
00685 {
00686     unsigned int deg;
00687 
00688 #ifndef VIDEO_FAST
00689     if(start > end){
00690         deg   = end;
00691         end   = start;
00692         start = deg;
00693     }
00694 #endif
00695 
00696     for(deg = start; deg < end; deg++){
00697         VIDEO_point_(x + (double)r * tcos[deg], y + (double)r * tsin[deg]);
00698     }
00699 
00700     return;
00701 }
00702 
00703 
00704 
00705 
00706 /**************************************************************************************************
00707 *****                                                                                         *****
00708 *****                        FONTX2 Driver 依存関数群                                         *****
00709 *****                                                                                         *****
00710 **************************************************************************************************/
00711 
00712 
00713 #ifdef VIDEO_MIRROR
00714 inline static unsigned char reverse (unsigned char buf)
00715 {
00716     return(
00717             ((buf & 0b00000001) << 7)
00718         +   ((buf & 0b00000010) << 5)
00719         +   ((buf & 0b00000100) << 3)
00720         +   ((buf & 0b00001000) << 1)
00721         +   ((buf & 0b00010000) >> 1)
00722         +   ((buf & 0b00100000) >> 3)
00723         +   ((buf & 0b01000000) >> 5)
00724         +   ((buf & 0b10000000) >> 7)
00725     );
00726 
00727 }
00728 #endif
00729 
00730 
00731 /**************************************************************************************************
00732 キャラクタ側の座標をセット
00733 **************************************************************************************************/
00734 void VIDEO_locate(unsigned int x, unsigned int y)
00735 {
00736 #ifdef VIDEO_MIRROR
00737     video.cx = NTSC_WIDTH / FONTX2_get_ascii_width() - x - 1;
00738 #else
00739     video.cx = x;
00740 #endif
00741     video.cy = y;
00742     return;
00743 }
00744 
00745 
00746 /**************************************************************************************************
00747 文字を描く / VRAMへフォントを転送する
00748 **************************************************************************************************/
00749 void VIDEO_putch(unsigned char c)
00750 {
00751     /* 文字列の連続出力のための、折り返し処理 */
00752 #ifdef VIDEO_MIRROR
00753     if(video.cx == 0){
00754         video.cx = NTSC_WIDTH / FONTX2_get_ascii_width();
00755         //video.cy++;
00756     }
00757 #else
00758     if(video.cx >= (NTSC_WIDTH / FONTX2_get_ascii_width())){
00759         video.cx = 0;
00760         video.cy++;
00761     }
00762 #endif
00763 
00764     if(video.cy >= (NTSC_HEIGHT / FONTX2_get_ascii_height())){
00765         video.cy = 0;
00766     }
00767 
00768 #if defined FONT_FAST8
00769 {
00770     /* フォントをバイト単位で VRAMへ転送する */
00771     unsigned char i;
00772     unsigned int *vram;
00773     unsigned char *font;
00774 
00775     vram = &ntsc.vram[ video.cy * FONTX2_get_ascii_height() * (NTSC_WIDTH >> 4) + (video.cx >> 1)];
00776     font = FONTX2_get_ascii_font(c);
00777 
00778     if(video.cx & 0x01){
00779         for(i = 0; i < FONTX2_get_ascii_height(); i++){
00780             *vram &= 0xff00;
00781 #ifdef VIDEO_MIRROR
00782             *vram |= (int)reverse(*font++);
00783 #else
00784             *vram |= (int)(*font++);
00785 #endif
00786              vram += (NTSC_WIDTH >> 4);
00787         }
00788     } else {
00789         for(i = 0; i < FONTX2_get_ascii_height(); i++){
00790             *vram &= 0x00ff;
00791 #ifdef VIDEO_MIRROR
00792             *vram |= (int)reverse(*font++) << 8;
00793 #else
00794             *vram |= (int)(*font++) << 8;
00795 #endif
00796              vram += (NTSC_WIDTH >> 4);
00797         }   
00798     }
00799 }
00800 #else
00801 {
00802     /* フォントを VRAMへ転送する。遅いけれど、byte単位以外の変態フォントサイズに対応するため */
00803 
00804     unsigned int x, y, i, j, k;
00805     unsigned char grif;
00806 
00807     for(y = 0; y < FONTX2_get_ascii_height(); y++){
00808 
00809         i = FONTX2_get_ascii_height() * video.cy + y;
00810 
00811         for(j = 0; j < FONTX2_get_ascii_width_byte(); j++){
00812 
00813 #ifdef VIDEO_MIRROR
00814             grif = reverse(FONTX2_get_ascii_font_data(c, j, y));
00815 #else
00816             grif = FONTX2_get_ascii_font_data(c, j, y);
00817 #endif
00818 
00819             for(x = 0; x < 8 && (j * 8 + x) < FONTX2_get_ascii_width(); x++){
00820 
00821                 k = x + video.cx * FONTX2_get_ascii_width();
00822 
00823                 if(grif & 0x80) ntsc.vram[(i << 4) + (k >> 4)] |=  (0x8000 >> (k & 0x0F));
00824                 else            ntsc.vram[(i << 4) + (k >> 4)] &= ‾(0x8000 >> (k & 0x0F));
00825 
00826                 grif = grif << 1;
00827             }
00828         }
00829     }
00830 }
00831 #endif
00832 
00833 #ifdef VIDEO_MIRROR
00834     video.cx--;
00835 #else
00836     video.cx++;
00837 #endif
00838     return;
00839 }
00840 
00841 
00842 /**************************************************************************************************
00843 文字列を描く
00844 **************************************************************************************************/
00845 void VIDEO_putstr(const char *s)
00846 {
00847     while(*s){
00848         VIDEO_putch(*s++);
00849     }
00850 
00851     return;
00852 }
00853 
00854 /**************************************************************************************************
00855 16進を描く
00856 **************************************************************************************************/
00857 void VIDEO_puthex(unsigned char a)
00858 {
00859     VIDEO_putch(hex[(a >> 4) & 0x0f]);
00860     VIDEO_putch(hex[ a       & 0x0f]);
00861     return;
00862 }
00863 
00864 
00865 /**************************************************************************************************
00866 2進を描く
00867 **************************************************************************************************/
00868 void VIDEO_putbin(unsigned char a)
00869 {
00870     VIDEO_putch('0' + ((a >> 7) & 0x01));
00871     VIDEO_putch('0' + ((a >> 6) & 0x01));
00872     VIDEO_putch('0' + ((a >> 5) & 0x01));
00873     VIDEO_putch('0' + ((a >> 4) & 0x01));
00874     VIDEO_putch('0' + ((a >> 3) & 0x01));
00875     VIDEO_putch('0' + ((a >> 2) & 0x01));
00876     VIDEO_putch('0' + ((a >> 1) & 0x01));
00877     VIDEO_putch('0' + ( a       & 0x01));
00878 
00879     return;
00880 }
00881 
00882 
00883 /**************************************************************************************************
00884 10進を描く (printfの代わり)
00885 **************************************************************************************************/
00886 void VIDEO_putuint(unsigned int digit, unsigned char size)
00887 {
00888     if(size > 4){ if(digit > 9999){ VIDEO_putch('0' + digit / 10000 % 10); } else { VIDEO_putch(' '); }; };
00889     if(size > 3){ if(digit >  999){ VIDEO_putch('0' + digit /  1000 % 10); } else { VIDEO_putch(' '); }; };
00890     if(size > 2){ if(digit >   99){ VIDEO_putch('0' + digit /   100 % 10); } else { VIDEO_putch(' '); }; };
00891     if(size > 1){ if(digit >    9){ VIDEO_putch('0' + digit /    10 % 10); } else { VIDEO_putch(' '); }; };
00892 
00893     VIDEO_putch('0' + digit % 10);
00894     return;
00895 }
00896 
00897 
00898 void VIDEO_putint(int digit, unsigned char size)
00899 {
00900     if(digit < 0)   VIDEO_putch('-');
00901     else            VIDEO_putch(' ');
00902 
00903     digit = abs(digit);
00904 
00905     if(size > 4){ if(digit > 9999){ VIDEO_putch('0' + digit / 10000 % 10); } else { VIDEO_putch(' '); }; };
00906     if(size > 3){ if(digit >  999){ VIDEO_putch('0' + digit /  1000 % 10); } else { VIDEO_putch(' '); }; };
00907     if(size > 2){ if(digit >   99){ VIDEO_putch('0' + digit /   100 % 10); } else { VIDEO_putch(' '); }; };
00908     if(size > 1){ if(digit >    9){ VIDEO_putch('0' + digit /    10 % 10); } else { VIDEO_putch(' '); }; };
00909 
00910     VIDEO_putch('0' + digit % 10);
00911     return;
00912 }
00913 
00914 
00915 void VIDEO_putdouble(double digit, unsigned char size, unsigned char size2)
00916 {
00917     if(digit < 0)   VIDEO_putch('-');
00918     else            VIDEO_putch(' ');
00919 
00920     digit = abs(digit);
00921 
00922     if(size > 4){ if((unsigned int)digit > 9999){ VIDEO_putch('0' + (unsigned char)((unsigned int)(digit / 10000) % 10)); } else { VIDEO_putch(' '); }; };
00923     if(size > 3){ if((unsigned int)digit >  999){ VIDEO_putch('0' + (unsigned char)((unsigned int)(digit /  1000) % 10)); } else { VIDEO_putch(' '); }; };
00924     if(size > 2){ if((unsigned int)digit >   99){ VIDEO_putch('0' + (unsigned char)((unsigned int)(digit /   100) % 10)); } else { VIDEO_putch(' '); }; };
00925     if(size > 1){ if((unsigned int)digit >    9){ VIDEO_putch('0' + (unsigned char)((unsigned int)(digit /    10) % 10)); } else { VIDEO_putch(' '); }; };
00926     VIDEO_putch('0' + (unsigned char)((unsigned int)digit % 10));
00927     VIDEO_putch('.');
00928     VIDEO_putch('0' + (unsigned int)((unsigned int)(digit * 10.0) % 10));
00929     if(size2 > 1)   VIDEO_putch('0' + (unsigned int)((unsigned int)(digit *   100.0) % 10));
00930     if(size2 > 2)   VIDEO_putch('0' + (unsigned int)((unsigned int)(digit *  1000.0) % 10));
00931     if(size2 > 3)   VIDEO_putch('0' + (unsigned int)((unsigned int)(digit * 10000.0) % 10));
00932 
00933     return;
00934 }
00935 
00936 
00937 /**************************************************************************************************
00938 グラフ初期化
00939 **************************************************************************************************/
00940 void GRAPH_init(pGRAPH_T graph, unsigned int x, unsigned int y, unsigned int width, unsigned int height)
00941 {
00942     unsigned int i;
00943 
00944 #ifndef VIDEO_FAST                          /* このブロックは未検証 */
00945     if(width >= GRAPH_SIZE){
00946         width = GRAPH_SIZE;
00947     }
00948     if(x + width > NTSC_WIDTH){
00949         width = NTSC_WIDTH - x;
00950     }
00951     if(y + height > NTSC_HEIGHT){
00952         height = NTSC_HEIGHT - y;
00953     }
00954 #endif
00955 
00956     graph->x = x;
00957     graph->y = y;
00958     graph->width = width;
00959     graph->height = height;
00960     graph->ptr = 0;
00961 
00962     for(i = 0; i < GRAPH_SIZE; i++){
00963         graph->data[i] = 0;
00964     }
00965 
00966     return;
00967 }
00968 
00969 
00970 /**************************************************************************************************
00971 グラフにデータを入れる
00972 **************************************************************************************************/
00973 void GRAPH_putdata(pGRAPH_T graph, unsigned int data)
00974 {
00975     if(data > 100) data = 100;
00976 
00977     graph->data[graph->ptr] = data;
00978     graph->ptr = (graph->ptr + 1) % graph->width;
00979 
00980     return;
00981 }
00982 
00983 
00984 /**************************************************************************************************
00985 グラフを描く
00986 **************************************************************************************************/
00987 void GRAPH_draw_point(pGRAPH_T graph)
00988 {
00989     unsigned int i, w, x, y;
00990 
00991     for(i = graph->y; i < graph->y + graph->height; i++){
00992         VIDEO_point_(graph->x, i);
00993     }
00994 
00995     w = graph->width * 2;
00996     for(i = graph->width; i < w; i++){
00997         x = graph->x + i - graph->width;
00998 
00999         y = graph->y + (((unsigned int)graph->data[(graph->ptr + i - 1) % graph->width] *  graph->height) / 100);
01000         VIDEO_point_(x, y);
01001 
01002         y = graph->y + (((unsigned int)graph->data[(graph->ptr + i    ) % graph->width] *  graph->height) / 100);
01003         VIDEO_point(x, y);
01004     }
01005 
01006     return;
01007 }
01008 
01009 void GRAPH_draw_line(pGRAPH_T graph)
01010 {
01011     unsigned int i, w, x, y1, y2, y3;
01012 
01013     w = graph->width * 2 - 2;
01014     for(i = graph->width + 1; i < w; i++){
01015         x = graph->x + i - graph->width;
01016         y1 = graph->y + (((unsigned int)graph->data[(graph->ptr + i - 1) % graph->width] * graph->height) / 100);
01017         y2 = graph->y + (((unsigned int)graph->data[(graph->ptr + i    ) % graph->width] * graph->height) / 100);
01018         y3 = graph->y + (((unsigned int)graph->data[(graph->ptr + i + 1) % graph->width] * graph->height) / 100);
01019         VIDEO_line_(x, y1, x + 1, y2);
01020         VIDEO_line (x, y2, x + 1, y3);
01021     }
01022 
01023     for(i = graph->y; i < graph->y + graph->height; i++){
01024         VIDEO_point_(graph->x, i);
01025         VIDEO_point_(graph->x + graph->width, i);
01026     }
01027 
01028     return;
01029 }
01030 
01031 void GRAPH_draw_bar(pGRAPH_T graph)
01032 {
01033     unsigned int i, x, y;
01034 
01035     for(i = 0; i < graph->width; i++){
01036         x = graph->x + i;
01037         y = graph->y + (((unsigned int)graph->data[(graph->ptr + i) % graph->width] *  graph->height) / 100);
01038         VIDEO_line_(x, graph->y, x, y);
01039         VIDEO_line (x, y       , x, graph->y + graph->height);
01040     }
01041 
01042     return;
01043 }
01044 
01045 
01046 /**************************************************************************************************
01047 メータ初期化
01048 **************************************************************************************************/
01049 void METER_init(pMETER_T meter, unsigned int x, unsigned int y, unsigned char r)
01050 {
01051     meter->x = x;
01052     meter->y = y;
01053     meter->r = r;
01054     meter->old = 0;
01055 
01056     VIDEO_arc(x, y, r, 270, 360);
01057 
01058     return;
01059 }
01060 
01061 
01062 /**************************************************************************************************
01063 メータを描く
01064 **************************************************************************************************/
01065 void METER_draw(pMETER_T meter, unsigned int value)
01066 {
01067     double rc, rs;
01068 
01069     if(value > 100) value = 100;
01070 
01071     rc = (double)meter->r * tcos[0];
01072     rs = (double)meter->r * tsin[0];
01073     VIDEO_line(meter->x + rc, meter->y + rs, meter->x + 0.7 * rc, meter->y + 0.7 * rs);
01074 
01075     rc = (double)meter->r * tcos[270];
01076     rs = (double)meter->r * tsin[270];
01077     VIDEO_line(meter->x + rc, meter->y + rs, meter->x + 0.7 * rc, meter->y + 0.7 * rs);
01078 
01079     rc = (double)meter->r * tcos[meter->old];
01080     rs = (double)meter->r * tsin[meter->old];
01081     VIDEO_line_(meter->x + rc, meter->y + rs, meter->x + 0.7 * rc, meter->y + 0.7 * rs);
01082 
01083     meter->old = ((100 - value) * 27) / 10;
01084     rc = (double)meter->r * tcos[meter->old];
01085     rs = (double)meter->r * tsin[meter->old];
01086     VIDEO_line (meter->x + rc, meter->y + rs, meter->x + 0.7 * rc, meter->y + 0.7 * rs);
01087 
01088     return;
01089 }
01090 
01091 
01092 /**************************************************************************************************
01093 トラッカー初期化
01094 **************************************************************************************************/
01095 void TRACK_init(pTRACK_T track, unsigned int x, unsigned int y, unsigned int width, unsigned int height)
01096 {
01097     unsigned int i;
01098 
01099     track->x = x;
01100     track->y = y;
01101     track->width = width;
01102     track->height = height;
01103     track->ptr = 0;
01104 
01105     for(i = 0; i < TRACK_SIZE; i++){
01106         track->data[i][0] = 0;
01107         track->data[i][1] = 0;
01108     }
01109 
01110     return;
01111 }
01112 
01113 
01114 /**************************************************************************************************
01115 トラッカーにデータを入れる
01116 **************************************************************************************************/
01117 void TRACK_putdata(pTRACK_T track, unsigned int x, unsigned int y)
01118 {
01119     if(x > 100) x = 100;
01120     if(y > 100) y = 100;
01121 
01122     track->ptr = (track->ptr + 1) % TRACK_SIZE;
01123     track->data[ track->ptr ][0] = x;
01124     track->data[ track->ptr ][1] = y;
01125 
01126     return;
01127 }
01128 
01129 
01130 /**************************************************************************************************
01131 トラッカーを描く
01132 **************************************************************************************************/
01133 void TRACK_draw_point(pTRACK_T track)
01134 {
01135     unsigned int tmp;
01136 
01137     /* 消す */
01138     tmp = (track->ptr + 1) % TRACK_SIZE;
01139     VIDEO_point_(track->x + (track->width  * track->data[ tmp ][0]) / 100,
01140                  track->y + (track->height * track->data[ tmp ][1]) / 100);
01141 
01142     VIDEO_point_(track->x + (track->width  * track->data[ tmp ][0]) / 100 + 1,
01143                  track->y + (track->height * track->data[ tmp ][1]) / 100);
01144 
01145     VIDEO_point_(track->x + (track->width  * track->data[ tmp ][0]) / 100,
01146                  track->y + (track->height * track->data[ tmp ][1]) / 100 + 1);
01147 
01148     VIDEO_point_(track->x + (track->width  * track->data[ tmp ][0]) / 100 + 1,
01149                  track->y + (track->height * track->data[ tmp ][1]) / 100 + 1);
01150 
01151     VIDEO_point_(track->x + (track->width  * track->data[ tmp ][0]) / 100 + 2,
01152                  track->y + (track->height * track->data[ tmp ][1]) / 100);
01153 
01154     VIDEO_point_(track->x + (track->width  * track->data[ tmp ][0]) / 100,
01155                  track->y + (track->height * track->data[ tmp ][1]) / 100 + 2);
01156 
01157     VIDEO_point_(track->x + (track->width  * track->data[ tmp ][0]) / 100 + 1,
01158                  track->y + (track->height * track->data[ tmp ][1]) / 100 + 2);
01159 
01160     VIDEO_point_(track->x + (track->width  * track->data[ tmp ][0]) / 100 + 2,
01161                  track->y + (track->height * track->data[ tmp ][1]) / 100 + 1);
01162 
01163     VIDEO_point_(track->x + (track->width  * track->data[ tmp ][0]) / 100 + 2,
01164                  track->y + (track->height * track->data[ tmp ][1]) / 100 + 2);
01165 
01166 
01167     /* 描く */
01168     VIDEO_point(track->x + (track->width  * track->data[ track->ptr ][0]) / 100,
01169                 track->y + (track->height * track->data[ track->ptr ][1]) / 100);
01170 
01171     VIDEO_point(track->x + (track->width  * track->data[ track->ptr ][0]) / 100 + 1,
01172                 track->y + (track->height * track->data[ track->ptr ][1]) / 100);
01173 
01174     VIDEO_point(track->x + (track->width  * track->data[ track->ptr ][0]) / 100,
01175                 track->y + (track->height * track->data[ track->ptr ][1]) / 100 + 1);
01176 
01177     VIDEO_point(track->x + (track->width  * track->data[ track->ptr ][0]) / 100 + 1,
01178                 track->y + (track->height * track->data[ track->ptr ][1]) / 100 + 1);
01179 
01180     VIDEO_point(track->x + (track->width  * track->data[ track->ptr ][0]) / 100 + 2,
01181                 track->y + (track->height * track->data[ track->ptr ][1]) / 100);
01182 
01183     VIDEO_point(track->x + (track->width  * track->data[ track->ptr ][0]) / 100,
01184                 track->y + (track->height * track->data[ track->ptr ][1]) / 100 + 2);
01185 
01186     VIDEO_point(track->x + (track->width  * track->data[ track->ptr ][0]) / 100 + 1,
01187                 track->y + (track->height * track->data[ track->ptr ][1]) / 100 + 2);
01188 
01189     VIDEO_point(track->x + (track->width  * track->data[ track->ptr ][0]) / 100 + 2,
01190                 track->y + (track->height * track->data[ track->ptr ][1]) / 100 + 1);
01191 
01192     VIDEO_point(track->x + (track->width  * track->data[ track->ptr ][0]) / 100 + 2,
01193                 track->y + (track->height * track->data[ track->ptr ][1]) / 100 + 2);
01194 
01195 
01196     /* 十字を描く */
01197     tmp = track->y + (track->height >> 1);
01198     VIDEO_line(track->x, tmp, track->x + track->width, tmp);
01199 
01200     tmp = track->x + (track->width >> 1);
01201     VIDEO_line(tmp, track->y, tmp, track->y + track->height);
01202 
01203     return;
01204 }

OpenSSMに対してSat Aug 14 2010 03:23:43に生成されました。  doxygen 1.7.1