SPI RAM interface functions

Topics related to the API, programming discussions & questions, coding tips, bugs, etc. should go here.
User avatar
D3thAdd3r
Posts: 3222
Joined: Wed Apr 29, 2009 10:00 am
Location: Minneapolis, United States

Re: SPI RAM interface functions

Post by D3thAdd3r »

Do you have an earlier revision PCB and need the Uzenet expansion module? That is the type that connects onto the expansion port(so needs header pins too, if you didn't install those).

Assuming that is the case there is the newer and should be final version of the module, where the main addition I remember was /ESP_PROG so the '644 can reflash the firmware for the ESP8266. I just have a few of the old revision, and new revision console PCB but the newer Uzenet module would be the version you wanted, but right now only Alec has those things and I have none, so lets talk to him about getting those up on the store if possible.

I sponsored a $200 Uzenet prize for UCC where I was basically trying to get those distributed as much as possible. I am not sure that happened yet, so perhaps we can tap into that now for the purpose it was originally intended. The purpose I guess was to give an Uzenet module to any hardware winners(so just a couple), and after that basically anyone that wanted one until it ran dry. The PCBs were something like $2(have none yet), an ESP8266-12E or ESP8266-12F(only these two versions, plenty of these on hand) at around $3, and the SPI ram chip I think is $2(plenty of these). Maybe that money got spent on something else UCC related which would be fine also. I would probably sponsor UCC whenever it happens again early right now, just for that purpose. I would love to see expansion stuff developed for the next one, and also as some sort of justification to the ridiculous amount of time I have spent in development for Uzenet stuff at this point.
User avatar
Jubatian
Posts: 1564
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: SPI RAM interface functions

Post by Jubatian »

OK, I will polish that small example a bit to make it look a little better, then add it to the mainline (and yes, I remember I also still have a Mode 13 task laying around, to add the 30 tiles width scrolling support).

Nicksen: Currently you can not tell CUzeBox to not emulate an SPI RAM (neither to not emulate an SD Card or just have none inserted). You would be able to find this out by seeing that it doesn't respond to SPI RAM commands (so if you want to implement some sane message for people not having the module, you can do it this way: try something obvious, like writing a location and reading it back, preferably with two different values like 0x5A and 0xA5, if it doesn't work, report that there is no SPI RAM installed).

It would be nice though to still maintain these requirements in a clearly visible manner. For games, we should add flags like "SD Card", "SPI RAM", "ESP8266", "SNES Mouse", "2 players" and possibly whatever else necessary. This way someone building hardware on his own could see which games could he use on his system, or what he would have to add if he was interested in a particular game.

EDIT: I added the SD Card - SPI RAM interfacing demo to the Uzebox master repo.
User avatar
uze6666
Site Admin
Posts: 4801
Joined: Tue Aug 12, 2008 9:13 pm
Location: Montreal, Canada
Contact:

Re: SPI RAM interface functions

Post by uze6666 »

nicksen782 wrote: Mon Jul 10, 2017 12:25 am Then it seems that I need to get with the program.

So, how do I get the spiram and esp? I'd like to get one right away.
I have plenty of full size PCBs and Uzenet modules PCBs. I also have plenty of the parts required to make the modules so just send me a PM with what you need. For the Euzebox, it could be more tricky since Harty didn't put the header on his pcb. Lee made a hack for that though.

As a more formal way of distributing it, I will have to see to set up a new shop and I will not carry over the old one to the new server. Configuring OSCommerce was a real pain in the a** specially to integrate with CanadaPost. I would like to hope that in 10 years, some easy to use software has appeared.
User avatar
D3thAdd3r
Posts: 3222
Joined: Wed Apr 29, 2009 10:00 am
Location: Minneapolis, United States

Re: SPI RAM interface functions

Post by D3thAdd3r »

Quick question @Jubatian. I think I ran into a bug in the SPI Ram interface functions. The issue I ran into: I know I have the first 2 bytes of SPI ram as 0x00,0x20, but if I do a SpiRamReadU16(0,0), I will in fact retrieve a 16 bit value of 8192, which is equivalent to 0x20,0x00. The bytes are swapped from the normal MSByte order on AVR and reminds me of 6502 8-) Looking at the code for the 32 bit read, though I did not test, it seems also it would be exactly reversed 0,1,2,3 from the normal byte order 3,2,1,0 where 3 is MSByte. Seems like a small oversight and an easy fix, just wanted to make sure this wasn't intentional or I am not overlooking something.

Code: Select all

/*
** u16 SpiRamSeqReadU16(void);
** s16 SpiRamSeqReadS16(void);
**
** Sequentially reads unsigned or signed 16 bit value from SPI RAM.
**
** Outputs:
** r25:r24: Word read
** Clobbers:
** (Nothing)
*/
.global SpiRamSeqReadU16
.global SpiRamSeqReadS16
.section .text.SpiRamSeqReadS16
SpiRamSeqReadS16:
	jmp   SpiRamSeqReadU16
.section .text.SpiRamSeqReadU16
SpiRamSeqReadU16:

	in    r25,     SR_STAT
	sbrs  r25,     SR_TRAN ; Wait for completion of transmission
	rjmp  .-6
	in    r24,     SR_DR************r25********************
	out   SR_DR,   r25
	ldi   r25,     5
	dec   r25
	brne  .-4              ; (15)
	nop                    ; (16)
	in    r25,     SR_DR   ; (17)*****r24*******************
	out   SR_DR,   r25
	ret                    ; ( 4)
User avatar
Jubatian
Posts: 1564
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: SPI RAM interface functions

Post by Jubatian »

D3thAdd3r wrote: Mon Sep 25, 2017 3:09 amQuick question @Jubatian. I think I ran into a bug in the SPI Ram interface functions. The issue I ran into: I know I have the first 2 bytes of SPI ram as 0x00,0x20, but if I do a SpiRamReadU16(0,0), I will in fact retrieve a 16 bit value of 8192, which is equivalent to 0x20,0x00. The bytes are swapped from the normal MSByte order on AVR and reminds me of 6502 8-) (...)
This is intentional, the C language implementation uses Little Endian byte order (LSB first), and I wanted to keep being compatible with that. The AVR actually has no byte order enforced since it doesn't store or load multiple-byte values with own instructions. Register usage suggests Little Endian (in word operations and pointers the odd numbered register is high, on the ATMega this appears in the address space as 0x0000 - 0x001F access registers directly, so you would have Little Endian words there), stack usage Big Endian (call and ret stores and fetches return addresses which end up in Big Endian byte order on the stack).

I usually feel Big Endian more intuitive (especially when designing graphics as there usually high bits correspond to left pixels, which logically asks for Big Endian), but there I wanted to stick with the decision of the implementation of the C language.
User avatar
D3thAdd3r
Posts: 3222
Joined: Wed Apr 29, 2009 10:00 am
Location: Minneapolis, United States

Re: SPI RAM interface functions

Post by D3thAdd3r »

Ah yes thanks for the sanity check, I am laughing at myself now but that makes sense. I have always stored pointers/offsets on the SD that way, MSB,LSB, and did a (MSB<<8)|LSB as I was always just reading my arbitrary format into a buffer...I guess I was somehow that shielded from ever thinking about how asm and C interface...even though I knew the behavior of say ZL/ZH. I will just store pointers 0,1,2,3 as the read U16 and 32 functions are quite handy.
User avatar
D3thAdd3r
Posts: 3222
Joined: Wed Apr 29, 2009 10:00 am
Location: Minneapolis, United States

Re: SPI RAM interface functions

Post by D3thAdd3r »

How can this be made reliable to work with such things as the coveted SPI Vram mode, or any other place that the kernel requires immediate and overriding access to the SPI Ram from user code?

One possible way is to disallow anything but single byte reads. This hurts performance a lot I think, but it would be passable for streaming music at least. It seems to me there must be some addition that can be made to this library, which would facilitate this. But potentially it could be pretty messy, and bloat the whole thing where for people not requiring it kernel SPI Ram access, it hurts code space. Otherwise perhaps user code can only access via the kernel, but do you have any idea what the code for something like that would be?
User avatar
Jubatian
Posts: 1564
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: SPI RAM interface functions

Post by Jubatian »

D3thAdd3r wrote: Fri Oct 13, 2017 6:44 pmHow can this be made reliable to work with such things as the coveted SPI Vram mode, or any other place that the kernel requires immediate and overriding access to the SPI Ram from user code?
The SPI VRAM video mode will be just fine as long as you take care to build your application a little like Flight of a Dragon.

The point is that with an SPI heavy video mode, you still only have kernel SPI in the video frame driver. Mode74's SPI RAM sprites also can't interfere as Mode74 doesn't even support the traditional kernel's automatic sprite engine: you render sprites from the application, so you know exactly where you are making SPI accesses (by reading sprite data). Doing it like FoaD means that you set up your code so normally you won't get interrupted by a next video frame (or if you do, it is a reset, rendering halts, causing some flicker, but no harm otherwise).

So SPI RAM video modes can work all right without much trouble. Music streaming is which won't work since it normally wants to access SPI RAM even within VBlank (and for example Mode 748 also wouldn't tolerate it within the HBlanks since in some submodes the mixer is called within an SPI RAM access sequence which has to start before it to complete the row). You would have to make it at least partially a VSync mixer if you want to output audio from SPI RAM (like by replacing the PCM channel to a RAM based solution, and loading SPI RAM data into that by a call in each VBlank).

The VSync mixer by the way could be a lot smaller: 300 bytes would be all right even for the normal VSync mixer if the routine populating the buffer could wrap properly.
User avatar
D3thAdd3r
Posts: 3222
Joined: Wed Apr 29, 2009 10:00 am
Location: Minneapolis, United States

Re: SPI RAM interface functions

Post by D3thAdd3r »

Jubatian wrote: Fri Oct 13, 2017 7:13 pm The VSync mixer by the way could be a lot smaller: 300 bytes would be all right even for the normal VSync mixer if the routine populating the buffer could wrap properly.
That is quite interesting.
Jubatian wrote: Fri Oct 13, 2017 7:13 pm You would have to make it at least partially a VSync mixer if you want to output audio from SPI RAM (like by replacing the PCM channel to a RAM based solution, and loading SPI RAM data into that by a call in each VBlank).
If the above smaller vsync mixer could work and be backwards compatible, then I should say manually writing to the audio buffer is a fine solution for some things. I would be inclined to support a compression scheme based on keys and rolling errors or something like ADPCM, and make that code available as an option for the streaming music kernel. It should be possible for some games to have enough time to run say 3-4 "virtual PCM channels" simultaneously in addition to the normal channels. This seems like the type of thing that should never run from user code, for the reasons you mentioned.
Jubatian wrote: Fri Oct 13, 2017 7:13 pm Music streaming is which won't work since it normally wants to access SPI RAM even within VBlank (and for example Mode 748 also wouldn't tolerate it within the HBlanks since in some submodes the mixer is called within an SPI RAM access sequence which has to start before it to complete the row).
With this in mind perhaps I will change the way the streaming music stuff works to be more cooperative as the things you mention. Initially I imagined all these different ways it might be done and so wanted maximum flexibility for the user code, but really there is just one general way to do it and the game can instruct the kernel to buffer or not buffer data and the rest is automatic. Past that, I suppose the streaming player could simply require your SPI Ram Library to be there, and do most of the stuff the demo does in place, starting and stopping a sequential read with no assumptions about the previous state. It would make it simpler to use since you don't have to manually integrate the demo code, and closer to how simple it is to just trigger songs in the stock player. I am strongly considering this then.
User avatar
Jubatian
Posts: 1564
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: SPI RAM interface functions

Post by Jubatian »

D3thAdd3r wrote: Fri Oct 13, 2017 9:07 pmIf the above smaller vsync mixer could work and be backwards compatible (...)
It would be fine. Currently the Vsync mixer uses double-buffering (2 x 262 bytes buffers) which is unnecessary. It could be switched over to a FIFO buffer, this would work fine on the audio output, what can't do it is the code in soundMixerVsync.s. If you use 300 bytes, then you prefill it by about 20 bytes within the kernel on init, then start calling the VSync mixer once every frame (like normal), which is of course modified to handle a FIFO. It would output 262 bytes in the buffer on every frame while audio output would drain 262 bytes, so everything works. More than 262 bytes is actually just required to tolerate some jitter in the calling of the VSync mixer, and to allow for the VSync mixer to have a long execution time (several lines).
Post Reply