Last visit was: Mon Dec 09, 2024 6:21 am
It is currently Mon Dec 09, 2024 6:21 am



 [ 5 posts ] 
 TigerSOC draws Lissjous figures 
Author Message

Joined: Mon Jan 22, 2018 2:49 pm
Posts: 19
Software for the TigerSOC has come a long way since last December, and
continues to evolve.

For example, there are now sin and cos functions and bit-banging SPI interface
procedures for a pair of MCP4921 DACs. These were used to generate the
Lissajous figure shown below on my oscilloscope in xy mode.

1331 out of 4096 code and data locations are used in this demo, including a
512-word sin lookup table. Several metric tonnes of clock cycles are required
for each complete rendering.

My thanks to Dr Jefyll for the photo of the hardware, also shown below.


You do not have the required permissions to view the files attached to this post.


Fri Feb 07, 2020 2:25 am
User avatar

Joined: Tue Jan 15, 2013 5:43 am
Posts: 189
Lookin' good, Myron -- nice to see you sharing some of the mischief you've been up to! Here are a couple more photos for the folks, taken (rather hastily) with a hand-held camera.

Myron introduced his 12-bit creation in a previous post, including an exhaustively (even dauntingly) complete collection of files -- everything of any possible significance. But for me the "short but sweet" description is in the file Tiger_opcodes.txt, attached and excerpted below. As noted, each code location contains a packet of three 4-bit instructions. Thus, 16 instructions are available, and three 4-bit instructions can be fetched in a single memory access.

"Several metric tonnes of clock cycles are required for each complete rendering." Ohhhh-kay! :P

Good to see SPI being used, BTW. I might have to look into getting a pair of those MCP4921 DACs myself! 8-)

-- Jeff

Attachment:
Tiger_opcodes.txt
Quote:
// The Tiger programming model is:
// a data stack (d:) of 4 members
// a program counter stack (p:) of 8 members
// a physical memory space of 4096 code, data, and io locations
// The top of the program counter stack is the current program counter.
// There is no program status word, but see ADX re: arithmetic carry.

// Code locations contain a packet of three 4-bit instructions.
// During an instruction packet fetch, the current program counter is
// incremented to point to the next instruction packet
// (or the first of any inline data that satisfies instances of the LIT
// instruction in the current packet).


Attachment:
GEDC5944 .JPG


You do not have the required permissions to view the files attached to this post.

_________________
http://LaughtonElectronics.com


Fri Feb 07, 2020 4:48 am WWW

Joined: Mon Jan 22, 2018 2:49 pm
Posts: 19
Hello all, I thought it wouldn't hurt to regale you with some of the source code involved in the Lissajous demo.

I tip my hat to the Python3 crew for providing the substrate of the Tiger assembler. I've never had a more
pleasant experience writing an assembler in any other language, nor the resulting application source code
that inherits the full power of Python3. I'm amazed that declaring a sine lookup table is a one-liner,
as you will see below.

I might add that the assembler does not enforce matters of style, such as indentation. The only hard rule
is that multiple statements in a given line be separated by semicolons.

Code:
# cos and sin phase arguments are unsigned, analogous to 0..tau (0..2pi)

lbl('sine_lut'); data([int(MAXPOS*math.sin(n*math.tau/512)) for n in range(512)])

lbl('cos') # y y z phase -> y y z amplitude
  lit(SIGNBIT>>1); add() # a quarter turn, drop through
#
lbl('sin') # y y z phase -> y y z amplitude
  asr(); asr(); asr(); lit(511); band(); lit(sine_lut); add(); ld(); ret()


Code:
# respond to USB/UART keystrokes
lbl('command') # x x y z -> trash
  lit(rx_status); ld(); lit(fwd('no_command')); jz()
    lit(cr); call() # new line
    lit(uart); ld(); tt(); tt() # -> keystroke keystroke keystroke
    lit(tx); call() # echo
    # resolve defined keystroke commands, drop through if undefined
    lit(ord('h')); bxor(); lit(got_help); jz()
    lit(ord('u')); bxor(); lit(got_unit_circle); jz()
    lit(ord('X')); bxor(); lit(got_inc_xh); jz()
    lit(ord('x')); bxor(); lit(got_dec_xh); jz()
    lit(ord('Y')); bxor(); lit(got_inc_yh); jz()
    lit(ord('y')); bxor(); lit(got_dec_yh); jz()
    lit(ord('_')); bxor(); lit(got_inc_xpo); jz()
    lit(ord('-')); bxor(); lit(got_dec_xpo); jz()
    lit(ord('+')); bxor(); lit(got_inc_ypo); jz()
    lit(ord('=')); bxor(); lit(got_dec_ypo); jz()
lbl('no_command')
  ret()

lbl('init') # app initialization
  lit(got_help); call() # print help legend
  lit(got_unit_circle); call() # establish default xy parameters
lbl('doit') # main loop
    lit(command); call() # respond to user input
    # update the x DAC per cos, bump x phase
    lit(dac_x); lit(phacc_x); ld(); lit(phoff_x); ld(); add() # -> device phase
    lit(cos); call() # -> device amplitude
    lit(SIGNBIT); bxor() # convert signed to unsigned for DAC
    lit(mcp4921_update); call()
    lit(phacc_x); ld(); lit(phinc_x); ld(); add(); lit(phacc_x); st()
    # update the y DAC per sin, bump y phase
    lit(dac_y); lit(phacc_y); ld(); lit(phoff_y); ld(); add() # -> device phase
    lit(sin); call() # -> device amplitude
    lit(SIGNBIT); bxor() # convert signed to unsigned for DAC
    lit(mcp4921_update); call()
    lit(phacc_y); ld(); lit(phinc_y); ld(); add(); lit(phacc_y); st()
    #
    lit(pulse_nldac); call() # simultaneously update the x and y DAC output voltages
    lit(doit); jmp()


Thu Feb 13, 2020 8:30 pm
User avatar

Joined: Tue Jan 15, 2013 5:43 am
Posts: 189
Funny how your source code doesn't look like Forth, and doesn't look like assembly language, but is kinda sorta both!

eg: LD = Forth's @ ST = Forth's ! TT = Forth's DUP ADD = Forth's + etc.

Code:
lit(ord('x')); bxor(); lit(got_dec_xh); jz()
Lotsa Forth folk (including me) will find it odd that you don't underflow the stack when you repeatedly invoke lines like this (as you did in the example posted). I get that the stack only has 4 members. Apparently the oldest (deepest) member gets a copy of itself (not a deeper member) when the stack shrinks, is that an apt explanation? A bit of a brain bender. Need to forget the familiar scenario of a stack that lives in memory, addressed by a Stack Pointer, and instead think of a series of registers arranged as a LIFO structure (ie, no addresses involved, hence no Stack Pointer, and hence no pointer wraparound).

Any plans to finesse the assembler with the capability to accept IF ENDIF or similar? Just as an optional readability aid, I mean. Explicit jumps do have their place; I'm not saying they don't.

-- Jeff

_________________
http://LaughtonElectronics.com


Wed Feb 19, 2020 1:57 pm WWW

Joined: Mon Jan 22, 2018 2:49 pm
Posts: 19
Hey Dr Jefyll, thanks for your intelligent questions re: Tiger, and bringing up the F-word:)

Tiger implements a 2-stack RPN machine with its meager 16 instructions, but not a true Forth machine which would require many more.
The d-stack is best understood as a hyper-accumulator, with the significance of the 4 members changing in accordance with the
sequential execution of each instruction per "Tiger_opcodes.v", which is the definitive reference published within the zipfile
in the prior related topic viewtopic.php?f=15&t=661 (which you have renamed as the attachment
"Tiger_opcodes.txt" in your previous post).

One must understand all 16 of Tiger's instructions and the before -> after notation used to describe their behavior in order
to make sense of any example of code, or to write original code with any confidence.

The d-stack may be abused at the programmer's discretion (unlike Forth's obligation to balance the stack). On the other hand,
CPU logic will halt and light a dedicated LED in the event of a run-time p-stack error (too-many-call-levels or unbalanced-return).
See TigerCPU.v in the zipfile for the filthy details (Ctrl-f "sane").

Since Tiger lacks Forth stack-gymnastics instructions (except for the indispensable tt() (Forth dup)), named static variables
are used to buffer temporary data. In my opinion, clarity of expression benefits by avoiding the old shell game in the gnarly
parts of a non-trivial algorithm. In particular, I've been amazed how attempts to write "obviously-correct" code have worked
the first time even when I was a newbie programming this cub of my own creation. I hope that any valiant audience members will
enjoy similar success.

Constrained by the limit of no more than 4 d-stack members, one may write junk like:
Code:
...
    lit(uart); ld(); tt(); tt() # -> keystroke keystroke keystroke
    lit(tx); call() # echo
    # resolve defined keystroke commands, drop through if undefined
    lit(ord('h')); bxor(); lit(got_help); jz()
    lit(ord('u')); bxor(); lit(got_unit_circle); jz()
...

The first line primes the d-stack with 3 copies of keystroke.
The second line lit nudges keystroke into the persistent realm that you have correctly surmised (i.e. the stickiness of d[3],
the bottom of the d-stack).
The fourth and subsequent lines rely on the persistence of a flooded d-stack.

I have no plans to expand the assembler with structured programming syntax nor even the most obvious/common macros (eg. lld(uart)).
I have done so in past projects, but not doing so with Tiger facilitates codespace/timing analysis and novel control structures
beyond the traditional.

The seeming lack of addressing modes beyond the nuisance of lit-direct is actually the freedom to synthesize whatever mode the
programmer deems to be valuable in a given scenario. For example, interpreters and state machines are easily implemented.

BTW, my local TigerSOC directory has progressed far beyond the original Dec 2019 zipfile, but I have not spammed the forum with an
update. If requested, I will share the current snapshot which has all kinds of tested goodies and improved documentation. The current
zipfile is just over 7 Mbytes, mostly due to the inclusion of SPI device datasheets in the doc directory.


Thu Feb 20, 2020 1:11 pm
 [ 5 posts ] 

Who is online

Users browsing this forum: CCBot and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to:  
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software