Understanding the block move command

Designing hardware and software that uses the VS23S0X0 family of ICs as a 8-bit or SPI SRAM memory or as a Video Controller for generating Composite Video (TV-Out) or driving other kinds of displays.
Post Reply
mastmees
User
Posts: 3
Joined: Sat 2022-10-29 23:03

Understanding the block move command

Post by mastmees »

Hi. Given the following code the software version works as expected (very slowly of course) while the hardware accelerated version does not work. Completely messes up the screen and so on. Is it something that I am misunderstanding? I am trying to use the block mover to draw horizontal and vertical lines by setting the first pixel and then doing forward direction move 1 pixel forward, I don't believe this causes problems? I have spent many days now trying to decipher cryptic, or even conflicting statements between guide and datasheet (ie. guide says "Block skip is the amount of bytes between the two lines of block. The range is from 1 to 2048." while datasheet says "MVSKP Bits MVSKP bits define the amount of bytes between two lines of the moved block. The default value is 000h and the range is from 1 to 2048 (i.e. the actual amount of bytes is MVSKP+1).". Seriously, VLSI? And yes, I've tried both ways. something else is wrong here.

Code: Select all

#define HARDWARE_BLITTER
void VS23S010::blitter_op(uint32_t src, uint8_t w, uint8_t h, uint32_t dst, uint8_t backwards)
{
#ifndef HARDWARE_BLITTER
    if (!backwards) {
        for (int16_t i=0;i<h;i++) {
            for (int16_t j=0;j<w;j++) {
                uint8_t b=mem_read_byte(src++);
                mem_write_byte(dst++,b);
            }
            src+=linesize-w;
            dst+=linesize-w;
        }
    }
    else {
        for (int16_t i=0;i<h;i++) {
            for (int16_t j=0;j<w;j++) {
                uint8_t b=mem_read_byte(src--);
                mem_write_byte(dst--,b);
            }
            src-=linesize-w;
            dst-=linesize-w;
        }
    }
#else
    spi_select(true);
    spi_byte(BLOCKMVC1);
    spi_word(src>>1);
    spi_word(dst>>1);
    spi_byte(
        ((src&1)<<2) |
        ((dst&1)<<1) |
        BLOCKMVC1_PYF |
        (backwards?1:0)); // move direction, 1 is backwards
    spi_select(false);
    spi_select(true);
    spi_byte(BLOCKMVC2);
    spi_word(linesize-w-1);
    spi_byte(w);
    spi_byte(h-1);
    spi_select(false);
    while (block_move_active());
    spi_select(true);
    spi_byte(BLOCKMVST);
    spi_select(false);
#endif
}
Hannu
VLSI Staff
Posts: 542
Joined: Mon 2016-05-30 11:54
Location: Finland
Contact:

Re: Understanding the block move command

Post by Hannu »

Hello and welcome to the forum,

It has been a while since I've worked with video output of VS23S. However I'll try to check your findings. Am I correct if I assume you're working with VS23S010, not VS23S040?

First: Does your spi_select() work to right direction? The XCS pin is active low.

Could you tell what you write to video controller registers and what is linesize and how you call the function?
It would make my life easier and debugging much faster.
mastmees
User
Posts: 3
Joined: Sat 2022-10-29 23:03

Re: Understanding the block move command

Post by mastmees »

I am much, much beyond CS polarity problems. I just published the current state of the code at https://github.com/mastmees/vs23s10
This has line and rectangle drawing, fonts, character drawing and scrolling all working and block_move accelerated to the point where
the block_move works either by luck or workarounds to specific problems that I have identified.

for fast horizontal lines, lets say from X=0,Y=100 to X=200,Y=100 I would like to:

1. set pixel at (0,100) to desired color
2. do a block move of length 199, height 1 from address of (0,100) to address of (1,100), forward direction

What I expect to happen is block move will
1. copy pixel from (0,100) to (1,100)
2. increment source and destination addresses
3. copy the pixel it copied in step 1 from (0,100) to (1,100) one step forward, from (1,100) to (2,100)
4. increment source and destination addresses
...
repeat the above until 199 bytes copied
as the height was set to 1, finish

the result should be solid line of a same color as the initial pixel was set to. However, using the hardware block move, it will not be. I have since learned, that while the block mover can move 1 line (so I can draw filled rectangles by copying the first line), it will not copy the 1-line block correctly if it is less then 4 bytes wide. It also fails fails to move blocks that are 200 bytes wide, and 230 rows high, appearing to lose some bytes but I have not been able to figure out the exact failure pattern yet. Moving 8x10 pixel characters from off-screen memory to display area works completely as expected, so I feel rather confident that I have a good grip on forward direction moves at least.

All that said, I've already gotten to the point where the graphics primitives are very usably fast. My biggest concern at the moment is not drawing performance. It's the image quality. I hoped that external video buffer amplifier would help, but even the Analog Devices ADA4432-1 that has built-in lowpass filter helped only a little. Without VS23S010 luminance channel filter enabled the video output signal has massive overshoots on rising edges of vide signal, causing terrible color fringing. Enabling the filter significantly reduces the overshoots and color fringing, but causes another problem - significant positive polarity spike at pixel data start position, and negative polarity spike at the pixel data stop position. negative polarity spike below black level before the line is not too bad if the background is black anyway, as long as it is not mistaken for line sync. The positive spike at the start of pixel data, however, produces a grey line to appear on left edge of visual area.
Hannu
VLSI Staff
Posts: 542
Joined: Mon 2016-05-30 11:54
Location: Finland
Contact:

Re: Understanding the block move command

Post by Hannu »

Good to hear that you got the blitter working.

The VS23S010 video DAC is current DAC. It is designed so that the input of display terminates the output to 75 ohms.

What kind of electrical interface you have?
mastmees
User
Posts: 3
Joined: Sat 2022-10-29 23:03

Re: Understanding the block move command

Post by mastmees »

What do you mean "got the blitter working"? As I explained, I did not get it working for cases that I wanted it for, and even the operations that work only work in very limited set of conditions. Am I really the first person in the world who tries to use the block mover for these operations?

I understand that the output is current output, I have 75 ohm resistor to ground from output signal, before going into buffer amplifier. See attached diagram (bypass caps not shown for simplicity)
Attachments
output.png
output.png (59.59 KiB) Viewed 12278 times
Hannu
VLSI Staff
Posts: 542
Joined: Mon 2016-05-30 11:54
Location: Finland
Contact:

Re: Understanding the block move command

Post by Hannu »

I took a look at different designs. The basic circuit is the one which can be seen on datasheet with protecting TVS and it should work well. All of the designs have common that there is a some series resistance and I believe it is key to keep the signal overshooting because that is one of those things which haven't been issue before.

VS1005 dev board extension 1 has 10 ohm series resistors. And then for example 25||50 division is also seen for impedance matching amplification. Anyway that is analog design and with its own compromises.

I'll take another look if I can find or write some easy to understand example of the blitter because it should work.
Attachments
Adjust resistor values for your design requirements
Adjust resistor values for your design requirements
vs23_and_amp.png (7.37 KiB) Viewed 12274 times
Hannu
VLSI Staff
Posts: 542
Joined: Mon 2016-05-30 11:54
Location: Finland
Contact:

Re: Understanding the block move command

Post by Hannu »

I found the overshoot issue now that I tried enough old projects. I had forgotten it completely.

Code: Select all

/// The first pixel of the picture area, the X direction.
//#define STARTPIX (BLANKEND+13)
#define STARTPIX ((BLANKEND+13) & ~0xf)
// 4. Write picture start and end
	SpiRamWriteRegister(PICSTART, (STARTPIX-1));
	SpiRamWriteRegister(PICEND, (ENDPIX-1));
	
Write Picture Start value 28 <= 002fh

So keeping last least significant bits high, the overshoot disappears.

Code: Select all

VS1010>vs*
VS23S010 INIT
Read Manufacturer and Device ID	9f => 2b00
Manufacturer ID: 2b00
ID ok, 1 VS23 ICs in system
Linelen: 2260 PLL clks
Picture line area is 299 x 240
Upper left corner is point (0,0) and lower right corner (298,239)
Memory space available for picture bytes 127860
Free bytes 54180
Picture line 308 bytes
Picture length, 187 color cycles
Picture pixel bits 8
Start pixel 2f
End pixel ea
Index start address 8e0
Picture line 0 address c8c
Write Multi-IC Access Control	b8 <= 0eh
Write Status Register	01 <= 40h
Write Picture Start value	28 <= 002fh
Write Picture End value	29 <= 00eah
Write Video Display Controller Control1	2b <= 3000h
Write Line Length	2a <= 08d4h
Write Program	PROG:c09c0a4ah
Write Picture Index Start address	2c <= 0238h
Write Block Move Control1	34 <= 0000000010h
Write Video Display Controller Control2	2d <= d138h
Read Current Line value & PLL lock	53 => 801d
Current line: 801d
Write Block Move Control1	34 <= 55f037dc11h

VS1010>
I also got the block moving working. MoveBlock() is the last function in pal.c. I didn't test it with 16-bit pixels and there could be off by one errors.
I attached the VS1010 solution. It has been gathered from many projects so it looks rather ugly

So you can have fun with all #defines.

The IOCTL_START_FRAME ioctl() drives xcs down and IOCTL_END_FRAME releases. The mysterious spi0.Write() works like this when there isn't buffer.

Code: Select all

u_int16 DevHwSpiWrite(register __i0 MEDIUM_DEVICE *dev, void *buf, u_int16 sourceIndex, u_int16 bytes) {
        devHwSpiHwInfo *hw=(devHwSpiHwInfo*)dev->hardwareInfo;
        //printf(" HwSpiOutput:%dBytes ",bytes);                
        if (!buf) { //Send bytes copies of byte sourceIndex
                /*Must wait until end of transmission to switch to 8 bit mode*/
                if (hw->regs->config != __HWSPI_8BIT_MASTER) {
                        /*Must wait until end of transmission to switch from 8 bit to 16 bit mode*/
                        __HWSPI_WAIT_UNTIL_TX_IDLE();
                        hw->regs->config = __HWSPI_8BIT_MASTER;
                }
                while(bytes--) {
                        __HWSPI_WAIT_UNTIL_TX_FIFO_NOT_FULL();
                        hw->regs->data = sourceIndex; //send byte from "sourceIndex" parameter          
                }
                return S_OK;
        }
        while (bytes) {
                u_int16 w=0;
                if (bytes == 1) {
                        MemCopyPackedBigEndian(&w, 1, buf, sourceIndex++, 1);
                        /*Must wait until end of transmission to switch to 8 bit mode*/
                        __HWSPI_WAIT_UNTIL_TX_IDLE();
                        hw->regs->config = __HWSPI_8BIT_MASTER;
                        hw->regs->data = w;
                        bytes--;
                } else {
                        MemCopyPackedBigEndian(&w, 0, buf, sourceIndex, 2);
                        sourceIndex+=2;
                        bytes-=2;
                        if (hw->regs->config != __HWSPI_16BIT_MASTER) {
                                /*Must wait until end of transmission to switch from 8 bit to 16 bit mode*/
                                __HWSPI_WAIT_UNTIL_TX_IDLE();
                                hw->regs->config = __HWSPI_16BIT_MASTER;
                        }
                        __HWSPI_WAIT_UNTIL_TX_FIFO_NOT_FULL();
                        hw->regs->data = w;
                }                       
        }       
        return S_OK;
}
Attachments
The result of my testing
The result of my testing
my_test.jpg (156.73 KiB) Viewed 12257 times
vs23sdisplay.zip
Test software for the bliiter
(175.71 KiB) Downloaded 448 times
Post Reply