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

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

OpenSSMに対してThu Sep 9 2010 00:03:05に生成されました。  doxygen 1.7.1