Deze hexfile is toch duidelijk anders en werkt in MPsim.

Met installeren van MPLab heb ik nog nooit problemen gehad, en dat heb ik toch al heel vaak gedaan... (8.92 is inderdaad de laatste versie; MPLabX: nooit aan beginnen)

Op vrijdag 19 januari 2024 14:06:19 schreef SparkyGSX:
[...]Wellicht, maar dan kan hij niets anders meer doen.

Dat hoeft ook niet voor een simpele balkengenerator... ;)
Balken in grijstinten is trouwens ook geen probleem...

Op vrijdag 19 januari 2024 15:49:21 schreef Arco:
Deze hexfile is toch duidelijk anders en werkt in MPsim.

Met installeren van MPLab heb ik nog nooit problemen gehad, en dat heb ik toch al heel vaak gedaan... (8.92 is inderdaad de laatste versie; MPLabX: nooit aan beginnen)

[...]
Dat hoeft ook niet voor een simpele balkengenerator... ;)
Balken in grijstinten is trouwens ook geen probleem...

Ik had inderdaad MPLabX geïnstalleerd. Wat een drama. Gauw deinstalleren en MPLAB gebruiken. Maar wat moet ik nu met die 'language tool exception'?

Als het goed is zit er toch een ASM compiler in?

Ik gebruik altijd deze download uit de Microchip archives: https://ww1.microchip.com/downloads/en/DeviceDoc/MPLAB_IDE_8_92.zip
Complete project heb ik bijgevoegd in zipfile...

PAL_Sync.zip

Op vrijdag 19 januari 2024 16:06:12 schreef Arco:
Ik gebruik altijd deze download uit de Microchip archives: https://ww1.microchip.com/downloads/en/DeviceDoc/MPLAB_IDE_8_92.zip
Complete project heb ik bijgevoegd in zipfile...

[bijlage]

Die zipfile had ik vanmiddag ook genomen; dat werkt nu zonder language tool gedoe.

Het project openen strandt op:

Hij verwacht ergens iets dat niet kan worden gevonden.

Als ik met de ProjectWizzard een nieuw project aanmaak dan resulteert dat in:

Bij Project -> Build Options -> Project -> MPAssembler vinkje 'disable case sensitivity' aanzetten...
Nogmaals poging:

PAL_Sync (2).zip

[Bericht gewijzigd door Arco op (15%)]

Ok, dat is nu gelukt. Met de Project Wizzard heb ik een nieuw project gemaakt en de ASM ingevoegd. Compileren gaat nu goed met uitschakeling van Case Sensitivity (wie gebruikt dit dat nu? :? )

Een uitstapje, maar ik kan nu ASM files compileren.

Dit komt er nu uit:

Poort B.2 geeft een puls van 27uS hoog en ca 38uS laag (zal samen wel die 64 zijn).

Maar hij komt dus niet om de 20 milli Seconde (50Hz Vsync)

Het lijkt toch of je de oude hexfile gebruikt... (in MPsim werkt het hier wel)
Aangepaste project file (je kunt de binaire status van de outputs zien in het special function registers window.)

Voor debugger/simulator:

F5 = Halt
F6 = Reset
F7 = Single step
F9 = Run
F11 = Animate

PAL_Sync (3).zip

Met de laatste zip zou je ook de binaire status moeten zien in het SFR window. Nogmaals zip...

Op vrijdag 19 januari 2024 18:27:39 schreef Arco:
Met de laatste zip zou je ook de binaire status moeten zien in het SFR window. Nogmaals zip...

Ik heb de PIC eerst 'erased', daarna deze .hex opnieuw geflasht.
Dit komt er dan uit:

Puls van 24 uS hoog, 40 uS laag.

(valt me op dat die hex van 15:56 hr is, project is van 17:01 Hr)

Ik heb de debugger geprobeerd. F5, F7. F9 werkt. Bij F11 (animate) zie ik niks gebeuren (maar kijk vermoedelijk naar iets verkeerds)

Ik heb het resultaat bij wijze van proef even op de modulator aangesloten. Je ziet dat er totaal geen synchronisatie plaatsvindt. Ik had verwacht dat hij horizontaal wel zou syncen (omdat de 64uS horizontale syncpuls er wel is ) en verticaal zou rollen vanwege het ontbreken van de verticale sync.
Maar het is nu random...

https://youtube.com/shorts/9TvkzQmvmfU?

Ik zal eens kijken of ik mijn oude tv kan uitgraven op zolder dan kan ik het proberen...
Het laatste scoopbeeld klopt totaal niet met wat ik in de simulator zie...

[Bericht gewijzigd door Arco op (30%)]

Op vrijdag 19 januari 2024 22:47:38 schreef Arco:
Ik zal eens kijken of ik mijn oude tv kan uitgraven op zolder dan kan ik het proberen...
Het laatste scoopbeeld klopt totaal niet met wat ik in de simulator zie...

Maar hoe kan ik die simulator activeren? Dan zou ik het ook kunnen zien.

En hoe ziet het scopebeeld er bij jou dan uit? :?

Op vrijdag 19 januari 2024 22:01:09 schreef Bavelt:
Ik heb het resultaat bij wijze van proef even op de modulator aangesloten. Je ziet dat er totaal geen synchronisatie plaatsvindt. Ik had verwacht dat hij horizontaal wel zou syncen (omdat de 64uS horizontale syncpuls er wel is ) en verticaal zou rollen vanwege het ontbreken van de verticale sync.
Maar het is nu random...

Ik heb het vermoeden dat het doorlopen van de witte balk, ook in het blankinggebied, de H- oscillator steeds uit zijn vanggebied slaat, en zo de H-PLL er niet in slaagt om te locken. testen van dit vermoeden is eenvoudig, verwijder de witte balk uit het programma, en check of locken dan wel plaatstvind.

Een PAL synchronisatie signaal heeft een timing resolutie van 0,01us nodig voor het genereren van een correcte timing van de Equalizing/Serration pulses gedurende de vertikale blanking/sync. Een timing resolutie van maar 1us is daarvoor niet bruikbaar. Video (of aanverwante) apparatuur kan mogelijk bij het geheel ontbreken van Equalizing/Serration pulses (of een incorrecte timing daarvan) niet synchroniseren.

Op zaterdag 20 januari 2024 00:14:59 schreef Bobosje:
Een PAL synchronisatie signaal heeft een timing resolutie van 0,01us nodig voor het genereren van een correcte timing van de Equalizing/Serration pulses gedurende de vertikale blanking/sync. Een timing resolutie van maar 1us is daarvoor niet bruikbaar. Video (of aanverwante) apparatuur kan mogelijk bij het geheel ontbreken van Equalizing/Serration pulses (of een incorrecte timing daarvan) niet synchroniseren.

Je zoekt het wat te ver. dit is geen PAl ontvanger, (maar ook een pal ontvanger kan vrolijk syncen zonder egalisatiepulsen) maar een Z/W CCIR uit lang vervlogen tijden. of de sync nu 4,7 of 5 µsec duurt, het zal de ontvanger lak wezen.

Op vrijdag 19 januari 2024 23:54:29 schreef Bavelt:
En hoe ziet het scopebeeld er bij jou dan uit? :?

Scoopbeeld is wat lastig met alleen een simulatie... :+

Soms kan iets je bezighouden. Tot héél laat.
Midden in de nacht werd ik wakker en bleef ik me maar afvragen waarom het niet werkte.
Want Arco maakt - in tegenstelling tot mij - niet gauw fouten.

En ineens realiseerde ik me: de extra puls komt op Poort B.2. Heb ik de scope daar wel op hangen?

Rond 5.00 uur opgestaan, naar de werkkamer.

Nee dus, de scope hangt 'gewoon' aan poort B.0 en B.1 (pin 6 en 7)
Maar Poort B.2 is pin 8 van de PIC16F1847...

Wat erg, zijn anderen voor mij bezig en ik maak zo'n fout.
Nederigheid is hetgeen mij nu past.. En excuses ;( :/

Ik heb het net geprobeerd. Pin B.2 is laag, zonder puls...
Maar dat ga ik eerst vandaag maar eens zelf uitzoeken.

In 2013 heb ik zitten spelen met de LPC800 in 8 pin DIP uitvoering.
Dit is/was een NXP ARM processor met ik meen 1 kByte RAM

De uitdaging was om er een TV beeld mee te genereren en dat leidde to een PONG variant.
De TV output wordt met een 'state machine' constructie gemaakt en er is alleen een enkele lijnbuffer beschikbaar die door de SPI output met DMA naar buiten gestuurd wordt.
Het werkte verassend goed, had alleen een hardware bug ontdekt in de eerste generatie van de chips: de analoge comparator was 'dead'. Ik heb het gemeld aan NXP en kreeg een handvol verbeterde versies toegestuurd maar heb daarna er niets meer mee gedaan :D Ik had als alternatief voor de potmeters twee joysticks aangesloten (alleen up/down, serveren ging met up+down) maar je kon ook tegen de computer spelen.
Voor een ieder die geintereerd is in de (C) code:

/**************************************************************************/
/**************************************************************************/
//
// PONG by KGE (c)2013
// unfortunately the comparator function of my LPC810 seems to be broken
// so the analog controller is replaced by two simple buttons (up and down)
//
// Video output is serialized by the SPI function of the LPC
// line timing is done by the use of timer interrupts every 64 usec


// #define SINGLEPLAYER

#include <stdio.h>
#include "LPC8xx.h"
#include "gpio.h"
#include "mrt.h"
#include "uart.h"
#include "spi.h"
#include "string.h"

#if defined(__CODE_RED)
#include <cr_section_macros.h>
#include <NXP/crp.h>
__CRP const unsigned int CRP_WORD = CRP_NO_CRP ;
#endif


// let's try that for my sync pin..
#define SYNC_OUTPUT     (2)

// define IO pins for controller
#define RIGHT_PADDLE_UP        (4)
#define RIGHT_PADDLE_DOWN    (1)
#define LEFT_PADDLE_UP        (0)
#define LEFT_PADDLE_DOWN    (5)

// used in winner testing
#define LEFT 1
#define RIGHT 2

#define PORT0     0

// as it says: the line counter
volatile int line_counter;

// define PAL signals
#define VTOTAL             312                // total number of lines
#define VSYNC_START     (VTOTAL-8)        // start of vertical sync
#define VSYNC_END         (VTOTAL-4)        // end of vertical sync
#define VISIBLE_START    35                // start of visible area
#define VISIBLE_END        275                // end of visible area
#define HSYNCWIDTH        (12-1)            // width of horizontal synchronisation (SPI word size)
// #define HSYNCWIDTH        16-1

// note MAX_X is width in pixels
// MAX_Y is height in lines
#define MAX_X            208
#define MAX_Y            (VISIBLE_END-8)

// define BAT positions and size (in pixels/lines)
#define BAT_LEFT_XPOS     24                            // left bat horizontal position
#define BAT_RIGHT_XPOS     (MAX_X-BAT_LEFT_XPOS-8)        // right bat mirrored position
#define BAT_SIZE         31                            // the vertical size of the bat
#define BALL_HEIGHT        8                            // the vertical size of the ball
#define BALL_WIDTH        8                            // the horizontal size of the ball

#define ANGLE_STEPS        7                            // number of bounce steps on the bat
#define ANGLE_FACTOR    (BAT_SIZE/ANGLE_STEPS)        // the calculated factor for vertical movement

#define SCORE_LEFT_XPOS        ((MAX_X/2)-24)            // horizontal position of the left player score
#define SCORE_RIGHT_XPOS    ((MAX_X/2)+24)            // horizontal position of the right player score
#define SCORE_YPOS            (VISIBLE_START+10)        // vertical position of both scores

// standard speed setting
#define BALL_SPEED_X    2
#define BALL_SPEED_Y    1

// hardware init
void SwitchMatrix_Init()
{
       /* Enable SWM clock */
        LPC_SYSCON->SYSAHBCLKCTRL |= (1<<7);

        // Enable IOCON clock
        LPC_SYSCON->SYSAHBCLKCTRL |= (1<<18);

        /* Pin Assign 8 bit Configuration */
        /* SPI0_MOSI */
        LPC_SWM->PINASSIGN4 = 0xffffff03UL;

        /* Pin Assign 1 bit Configuration */
        /* RESET */

#ifdef SINGLEPLAYER
        LPC_SWM->PINENABLE0 = 0xffffffbfUL;
#else
        LPC_SWM->PINENABLE0 = 0xffffffffUL;
#endif
        /* Set the SYNC output pin to output (1 = output, 0 = input) */
        LPC_GPIO_PORT->DIR0 |= (1 << SYNC_OUTPUT);

        // switch PIO pins to input
        LPC_GPIO_PORT->DIR0 &= ~(1<< RIGHT_PADDLE_DOWN);
        LPC_GPIO_PORT->DIR0 &= ~(1<< RIGHT_PADDLE_UP);

        // init SPI to run at 30/6 = 5 MHz, no delay (0)
        spiInit(LPC_SPI0,(6-1),0);

        // disable IOCON clock
        LPC_SYSCON->SYSAHBCLKCTRL &= ~(1<<18);

        /* SWM clock no longer needed now it's configured */
        LPC_SYSCON->SYSAHBCLKCTRL &= ~(1<<7);
}

// the 'font'
static unsigned char bitmap[][8]={
        {255,129,129,129,129,129,129,255},    // 0
        {1,1,1,1,1,1,1,1},    // 1
        {255,1,1,255,128,128,128,255},    // 2
        {255,1,1,15,1,1,1,255},    // 3
        {129,129,129,255,1,1,1,1},    // 4
        {255,128,128,255,1,1,1,255},    // 5
        {255,128,128,255,129,129,129,255},    // 6
        {255,1,1,1,1,1,1,1},    // 7
        {255,129,129,255,129,129,129,255},    // 8
        {255,129,129,255,1,1,1,255},    // 9
        {24,60,126,126,126,126,60,24},    // ball
};

// storage space
volatile unsigned char linebuffer[(MAX_X/8)+1];            // single line display buffer
volatile unsigned short ball_x,ball_y;                    // storage for ball position
volatile unsigned short bat_left_ypos,bat_right_ypos;        // storage for bat positions
volatile unsigned short score_l,score_r;                    // storage for score (left and right player)

volatile unsigned char vbl_flag;                            // flag for signaling the vertical sync

// simple delay routine, n is the number of vertical syncs to wait
void wait(int n)
{
    while (n--)
    {
        vbl_flag=0;
        while (!vbl_flag);
    }
}

// the main event
int main(void)
{

    signed char dx,dy;
    unsigned char game_end=0;
    unsigned char winner=LEFT;
    unsigned char distx;
    unsigned char disty;
    int paused;

    unsigned char single_player=0;

    SystemCoreClockUpdate();    // retrieve the clock

    /* Initialise the GPIO block */
    gpioInit();

    /* Configure the switch matrix (setup pins) */
    SwitchMatrix_Init();

    /* Configure the multi-rate timer for 64us ticks and start interrupts */
    mrtInit(__SYSTEM_CLOCK/15525);

    // initial bat positions
    bat_left_ypos=100;
    bat_right_ypos=100;

    // reset score
    score_l=0;
    score_r=0;

    // reset ball
    ball_x=BAT_LEFT_XPOS+BALL_WIDTH;
    ball_y=bat_left_ypos+(BAT_SIZE/2)-(BALL_HEIGHT/2);


    if (!gpioGetPinValue(PORT0,RIGHT_PADDLE_UP)) single_player=1; else single_player=0;

    // startup delay (give monitor some time to sync and display)
    paused=150;    // startup delay
    game_end=1;    // force new game

    // endless loop
    while(1)
    {

            vbl_flag=0;
            while (!vbl_flag);            // wait for vsync to happen

            // are we is PAUSE mode ?
            if (paused)
            {
                // count down pause timer
                paused--;

                // test for new game
                if ((paused==0) && (game_end==1))
                {
                    // reset score
                    score_l=0;
                    score_r=0;

                    // reset ball
                    if (winner==LEFT)
                    {
                        ball_x=BAT_LEFT_XPOS+BALL_WIDTH;
                        ball_y=bat_left_ypos+(BAT_SIZE/2)-(BALL_HEIGHT/2);

                        // set vector
                        dx=BALL_SPEED_X;
                        dy=BALL_SPEED_Y;
                    }
                    else
                    {
                        ball_x=BAT_RIGHT_XPOS-BALL_WIDTH;
                        ball_y=bat_right_ypos+(BAT_SIZE/2)-(BALL_HEIGHT/2);
                        dx=-BALL_SPEED_X;
                        dy=BALL_SPEED_Y;
                    }
                    game_end=0;
                }
            }
            else
            {
                // move ball in X direction
                ball_x+=dx;
                // test for X limits
                if (ball_x > (MAX_X-8))
                {
                    if (dx>0)
                    {
                        if (score_l<9) score_l++;
                        // serve position halfway bat
                        ball_y=bat_left_ypos+(BAT_SIZE/2)-(BALL_HEIGHT/2);
                        ball_x=BAT_LEFT_XPOS+BALL_WIDTH;
                        dx=BALL_SPEED_X;
                        dy=BALL_SPEED_Y;
                        paused=50;
                        // wait(50);
                    }
                    else
                    {
                        if (score_r<9) score_r++;
                        // serve position halfway bat
                        ball_y=bat_right_ypos+(BAT_SIZE/2)-(BALL_HEIGHT/2);
                        ball_x=BAT_RIGHT_XPOS-BALL_WIDTH;
                        dx=-BALL_SPEED_X;
                        dy=BALL_SPEED_Y;
                        paused=50;
                        // wait(50);
                    }
                }

                if (score_r==9)
                {
                    game_end=1;
                    paused=200;
                    winner=RIGHT;
                }

                if (score_l==9)
                {
                    game_end=1;
                    paused=200;
                    winner=LEFT;
                }
                // move ball in Y direction
                ball_y+=dy;
                // bounce ball on Y limits
                if ((ball_y>(MAX_Y-1)) || (ball_y<VISIBLE_START))
                {
                    dy=-dy;
                }

                // test for collision with right bat
                if (dx>0)    // only if ball is moving right
                {
                    // calculate X distance
                    distx=BAT_RIGHT_XPOS - ball_x;
                    if (distx < BALL_WIDTH)
                    {
                        // calculate Y distance
                        disty=(ball_y + (BALL_HEIGHT/2)) - bat_right_ypos;
                        // we have a hit
                        if (disty < BAT_SIZE)
                        {
                            dx=-dx;
                            // calculate Y angle depending on position of impact on bat
                            dy=((disty-(BAT_SIZE/2))/ANGLE_FACTOR);
                        }
                    }
                }


                // test for collision with left bat
                if (dx<0)    // only if ball is moving left
                {
                    // calculate X distance
                    distx=ball_x - BAT_LEFT_XPOS;
                    if (distx < BALL_WIDTH)
                    {
                        // calculate Y distance
                        disty=(ball_y + (BALL_HEIGHT/2)) - bat_left_ypos;
                        // we have a hit
                        if (disty < BAT_SIZE)
                        {
                            dx=-dx;
                            // calculate Y angle depending on position of impact on bat
                            dy=((disty-(BAT_SIZE/2))/ANGLE_FACTOR);
                        }
                    }
                }
            }

            // test for single player mode
            if (single_player)
            {
                // play computer opponent on left bat
                // try and keep up with the Y position of the ball
                if ((ball_y>(bat_left_ypos+(BAT_SIZE-8))) && (bat_left_ypos<(VISIBLE_END-BAT_SIZE-1))) bat_left_ypos+=2;
                if ((ball_y<bat_left_ypos) && (bat_left_ypos>VISIBLE_START)) bat_left_ypos-=2;
            }
            else
            {
                // handle left paddle
                if (!gpioGetPinValue(PORT0,LEFT_PADDLE_DOWN) && (bat_left_ypos<(VISIBLE_END-BAT_SIZE-1)))
                {
                    bat_left_ypos+=2;
                }

                if (!gpioGetPinValue(PORT0,LEFT_PADDLE_UP) && (bat_left_ypos>(VISIBLE_START)))
                {
                    bat_left_ypos-=2;
                }
            }

            // handle right paddle
            if (!gpioGetPinValue(PORT0,RIGHT_PADDLE_DOWN) && (bat_right_ypos<(VISIBLE_END-BAT_SIZE-1)))
            {
                bat_right_ypos+=2;
            }

            if (!gpioGetPinValue(PORT0,RIGHT_PADDLE_UP) && (bat_right_ypos>(VISIBLE_START)))
            {
                bat_right_ypos-=2;
            }
        }

}


// This is the pseudo state machine for the video output generator

// dummy state
static void state_before_vsync(void);

// this is needed for every line in a frame of video
static void hsync()
{
    // set sync pin low
    LPC_GPIO_PORT->CLR0 = 1 << SYNC_OUTPUT;

    // send three more nulls (sync width)
    while ( (LPC_SPI0->STAT & SPI_STAT_TXRDY) == 0 );
    LPC_SPI0->TXDATCTL = SPI_TXDATCTL_FSIZE(HSYNCWIDTH)| SPI_TXDATACTL_RXIGNORE ;
    while ( (LPC_SPI0->STAT & SPI_STAT_TXRDY) == 0 );
    LPC_SPI0->TXDATCTL = SPI_TXDATCTL_FSIZE(HSYNCWIDTH)| SPI_TXDATACTL_RXIGNORE ;
    while ( (LPC_SPI0->STAT & SPI_STAT_TXRDY) == 0 );
    LPC_SPI0->TXDATCTL = SPI_TXDATCTL_FSIZE(HSYNCWIDTH)| SPI_TXDATACTL_RXIGNORE ;

    // set sync pin high
    LPC_GPIO_PORT->SET0 = 1 << SYNC_OUTPUT;

}

// setup initial state
static void (*state)(void) = state_before_vsync;

// emit a line from the visible area (framebuffer)
static void state_visible_area(void) {
    register unsigned short ofs_y;
    register unsigned short ofs_x;
    register unsigned short temp16;
    extern volatile unsigned char linebuffer[];
    int n;

    // always start by emitting a horizontal sync pulse
    hsync();

    // if not yet in the active part of the screen we're done here so just return
    if (line_counter < VISIBLE_START) return;

    // but if within visible part...
    if( line_counter<(VISIBLE_END+1))
    {
        // emit back porch (black level)
        while ( (LPC_SPI0->STAT & SPI_STAT_TXRDY) == 0 ); // wait for SPI register to be flushed
        LPC_SPI0->TXDATCTL = SPI_TXDATCTL_FSIZE(16-1) | SPI_TXDATACTL_RXIGNORE;
        while ( (LPC_SPI0->STAT & SPI_STAT_TXRDY) == 0 ); // wait for SPI register to be flushed
        LPC_SPI0->TXDATCTL = SPI_TXDATCTL_FSIZE(8-1) | SPI_TXDATACTL_RXIGNORE;


        // active line part
        // now send MAX_X dots

        // send contents of linebuffer
        for(n=0; n<(MAX_X/8); n++){
            while ( (LPC_SPI0->STAT & SPI_STAT_TXRDY) == 0 ); // wait for SPI register to be flushed
            LPC_SPI0->TXDATCTL = SPI_TXDATCTL_FSIZE(8-1) | linebuffer[n] | SPI_TXDATACTL_RXIGNORE;
            linebuffer[n]=0;    // clear linebuffer along the way
        }

        // now send 1 byte blanking to set black level
        while ( (LPC_SPI0->STAT & SPI_STAT_TXRDY) == 0 ); // wait for SPI register to be flushed
        LPC_SPI0->TXDATCTL = SPI_TXDATCTL_FSIZE(8-1)| SPI_TXDATACTL_RXIGNORE ;

        // create dotted vertical center line
        linebuffer[MAX_X/16]=(line_counter & 0x08);

        // place appropriate line of left and right bats and score
        ofs_y=line_counter-bat_left_ypos;
        if (ofs_y<BAT_SIZE) linebuffer[BAT_LEFT_XPOS/8]|=0x0f;

        ofs_y=line_counter-bat_right_ypos;
        if (ofs_y<BAT_SIZE) linebuffer[BAT_RIGHT_XPOS/8]|=0xf0;

        // stretch 8 line font for score to double size (16) by dividing ofs_y by two
        ofs_y=line_counter-SCORE_YPOS;
        if (ofs_y<16)
        {
            linebuffer[SCORE_LEFT_XPOS/8]|=bitmap[score_l][ofs_y>>1];
            linebuffer[SCORE_RIGHT_XPOS/8]|=bitmap[score_r][ofs_y>>1];
        }

        // place the ball
        ofs_y=line_counter-ball_y;
        if (ofs_y<8)
        {
            // divide by 8
            ofs_x=ball_x>>3;

                // pre shift object data
                temp16=bitmap[10][ofs_y]<<(8-(ball_x % 8));
                // place object data in linebuffer
                linebuffer[ofs_x]|=(temp16>>8);
                linebuffer[ofs_x+1]|=(temp16 & 0xff);
        }
    }
    else    // we're beyond the active screen part so just emit blank lines until vsync
    {
        state = state_before_vsync;
    }
}

// VSYNC is over, now wait for end of frame
static void state_after_vsync(void)
{

    // always emit horizontal sync
    hsync();

    if (line_counter != VTOTAL) return;

    line_counter = 0;                   // reset line counter
    vbl_flag=1;
    state = state_visible_area;         // we're in visible mode


}

// VSYNC is active
static void state_during_vsync(void)
{

    // keep sending horizontal sync pulses (but inverted)
    LPC_GPIO_PORT->SET0 = 1 << SYNC_OUTPUT;

    // send three more nulls (sync width)
    while ( (LPC_SPI0->STAT & SPI_STAT_TXRDY) == 0 );
    LPC_SPI0->TXDATCTL = SPI_TXDATCTL_FSIZE(HSYNCWIDTH)| SPI_TXDATACTL_RXIGNORE ;
    while ( (LPC_SPI0->STAT & SPI_STAT_TXRDY) == 0 );
    LPC_SPI0->TXDATCTL = SPI_TXDATCTL_FSIZE(HSYNCWIDTH)| SPI_TXDATACTL_RXIGNORE ;
    while ( (LPC_SPI0->STAT & SPI_STAT_TXRDY) == 0 );
    LPC_SPI0->TXDATCTL = SPI_TXDATCTL_FSIZE(HSYNCWIDTH)| SPI_TXDATACTL_RXIGNORE ;

    // set sync pin low
    LPC_GPIO_PORT->CLR0 = 1 << SYNC_OUTPUT;

    if (line_counter != VSYNC_END) return;

    LPC_GPIO_PORT->SET0 = 1 << SYNC_OUTPUT;
    state = state_after_vsync;          // VSYNC is done
}

static void state_before_vsync(void)
{
    // always emit horizontal sync
    hsync();
    // wait for VSYNC start
    if (line_counter != VSYNC_START)        return;

    state = state_during_vsync;     // VSYNC has started
}



void MRT_IRQHandler(void)
{
    // test IRQ register if it was caused by the timer
    if ( LPC_MRT->Channel[0].STAT & MRT_STAT_IRQ_FLAG )
    {
        state();    // here the active state is executed
        line_counter++;    // advance line counter

        LPC_MRT->Channel[0].STAT = MRT_STAT_IRQ_FLAG;      /* clear interrupt flag */
    }
    return;
}

Op zaterdag 20 januari 2024 00:36:47 schreef Arco:
[...]
Scoopbeeld is wat lastig met alleen een simulatie... :+

Er komt inderdaad een positieve puls op B.2. Keurig om de 20 mS,
hij is 17uS lang.
Op mijn scope is een combinatie 17uS per 20ms moeilijk waar te nemen.
De logic Analyzer echter geeft het keurig weer. (wat een fijn tool is dat toch.. :) )

In het uiteindelijke videosignaal zou deze dan 'inverse' moeten zijn, d.w.z 17uS laag.

Op het moment van de positieve puls op B.2 moet er op B.0 een negatieve puls van 20uS zijn...
B.2 is er alleen voor triggeren van de scoop. Kun je die LA ook laten triggeren op het B.2 signaal?

Ja, dat kan. Hierbij het resultaat:

.
.
En uitvergroot:

Dit lijkt dus gewoon goed te gaan.

NB nogmaals excuses voor de blunder met die poort...

Kan iedereen wel eens gebeuren.. :)
De spanningsnivo's zijn ook goed? (ik heb geen idee hoeveel afwijking daarin is toegestaan)