PDA

View Full Version : LMM



Jay Kickliter
03-29-2009, 05:58 AM
Ale said...

Hei Jay,

I do the following for LMM code:

lmm_pc is the PC in the LMM kernel. Manipulating it directly allows for jumps to +64/-63 instructions.


lmm_jump
rdlong lmm_pc, lmm_pc ' access long just after call to lmm_jump
add lmm_pc, #16 ' adjust for real address
jmp #lmm_fetch


lmm_fetch
rdlong lmm_i, lmm_pc
add lmm_pc, #4 ' next inst
lmm_i
nop
jmp #lmm_fetch

...


somewhere your LMM code:

mov somevar, #500
jmp #lmm_jump
long @some_label

...

somelabel
mov somevar, #200

mov var_1, #500
...
sub lmm_pc, #($-somelabel-1)*4 ' This is a jump backwards to somelabel


someloop:
add lmm_pc, #(someotherlabel - 1 - $)*4 ' jump forwards





That kind of LMM does not need anything extra from the compiler and works very well!
The rest of the code that access variables and subroutines in COG do not need any change, because it will be run from COG RAM as any other instruction. Only jumps or calls to LMM code need to work around different address range. Two small routines can take care of that (lmm_jump, lmm_call).



I didn't want to continue this on the other thread, since it turns out I don't need any special compiler support. Ale, do you happen to have any working examples of this that you'd be willing to share?

Ale
03-30-2009, 04:15 AM
I have them in my other machine http://forums.parallax.com/images/smilies/wink.gif. I'll post them tomorrow if it is ok with you. But be warned... it is exactly like that one http://forums.parallax.com/images/smilies/smile.gif, but with other names. I have some menu system for LCDs running on LMM basically a User interface. All supporting and drawing routines are in COG.

Ale
03-30-2009, 02:09 PM
Here is my actual code. I just added some documentation. If you have questions please do not hesitate to ask. The drawing routines and so on (used in the LMM code) are not included nor necessary.
All calls to LMM related routines... start with krnl_. Registers are krnl_r0 to krnl_r15. Another set of registers exist (k4_a to k4_g mapped to the other set).




DAT ' C4
' ************************************************** *************
' ************************************************** *************
' ************************************************** *************
'
' display refresh, oscilloscopes, fft, other data
'
'
' This is a lmm kernel with some drawing routines
'
' kernel routines like krnl_jmp/call etc do not need to be calls
' because return address is discarded and changed by krnl_fetch
' at the end of routine
'
' ************************************************** *************
' ************************************************** *************
' ************************************************** *************

org

c4_start
krnl_init mov krnl_pc,PAR
sub krnl_pc,#4
mov krnl_sp,krnl_pc ' stack starts before program
krnl_inc_pc add krnl_pc,#4
krnl_fetch rdlong krnl_inst,krnl_pc
add krnl_pc,#4
krnl_inst nop
jmp #krnl_fetch

krnl_r0 long 0
krnl_r1 long 0
krnl_r2 long 0
krnl_r3 long 0
krnl_r4 long 0
krnl_r5 long 0
k4_a
krnl_r6 long 0
k4_b
krnl_r7 long 0
k4_c
krnl_r8 long 0
k4_d
krnl_r9 long 0
k4_e
krnl_r10 long 0
k4_f
krnl_r11 long 0
k4_g
krnl_r12 long 0
k4_h
krnl_r13 long 0
k4_i
krnl_r14 long 0
krnl_lr long 0
krnl_sp long 0
krnl_pc long 0
krnl_cnt_ofsmsk long $7fff
krnl_cnt_cntmsk long $3ffff
krnl_t1 long 0
krnl_t2 long 0
' Scratch for call
krnl_call_ret
krnl_jmp_ret
krnl_rts_ret
krnl_push_lr_ret
krnl_pop_lr_ret
krnl_get_arg_ret
krnl_push_arg_ret
krnl_load_cnt_ret
krnl_load_adr_ret
krnl_exit_ret
long 0


' performs a call, return address is
' saved in the link register, dest address follows
' This can be combined with flags
'
' if_z jmp #krnl_call
' long @address

krnl_call mov krnl_lr,krnl_pc ' save PC in link register
add krnl_lr,#4
rdlong krnl_pc,krnl_pc ' address of destination
add krnl_pc,#16 ' adjust for real address
jmp #krnl_fetch
' Performs a jump, address follows
' This can be combined with
' flags
'
' if_z jmp #krnl_jmp
' long @address
'
krnl_jmp rdlong krnl_pc,krnl_pc ' reads address of destination
add krnl_pc,#16 ' adjust for real address
jmp #krnl_fetch

' returns from a call using the value in the link register
' this could be avoided later on using just a mov
krnl_rts mov krnl_pc,krnl_lr
jmp #krnl_fetch

' pushes the link register to the stack
krnl_push_lr sub krnl_sp,#4
wrlong krnl_lr,krnl_sp
jmp #krnl_fetch

' pops the link register from the stack
krnl_pop_lr rdlong krnl_lr,krnl_sp
add krnl_sp,#4
jmp #krnl_fetch ' stack underflow shoud be checked here

' gets an argument from stack
' the long that follows has 2 arguments
'
' 31 23 22 18 17 0
' +----------+-----+--------+
' | Addr_reg | 0 | offset |
' +----------+-----+--------+

krnl_get_arg rdlong krnl_t1,krnl_pc
mov krnl_t2,krnl_t1
shr krnl_t1,#23 ' address of destination register!
movd krnl_get_arg_g,krnl_t1 ' sets dest address
and krnl_t2,krnl_cnt_ofsmsk
add krnl_t2,krnl_sp
krnl_get_arg_g rdlong 0,krnl_t2
jmp #krnl_inc_pc ' next instruction

' puts an argument back to the stack
' the long that follows has 2 arguments
'
' 31 23 22 18 17 0
' +----------+-----+--------+
' | Addr_reg | 0 | offset |
' +----------+-----+--------+

krnl_put_arg rdlong krnl_t1,krnl_pc
mov krnl_t2,krnl_t1
shr krnl_t1,#23 ' address of destination register!
movd krnl_put_arg_g,krnl_t1 ' sets dest address
and krnl_t2,krnl_cnt_ofsmsk
add krnl_t2,krnl_sp
krnl_put_arg_g wrlong 0,krnl_t2
jmp #krnl_inc_pc ' next instruction

' loads a constant into a register
' the long that follows has 2 arguments
'
' 31 23 22 18 17 0
' +----------+-----+--------+
' | Addr_reg | 0 | cnt |
' +----------+-----+--------+
krnl_load_cnt rdlong krnl_t1,krnl_pc
mov krnl_t2,krnl_t1
shr krnl_t1,#23 ' address of destination register!
movd krnl_load_cnt_g,krnl_t1 ' sets dest address
and krnl_t2,krnl_cnt_cntmsk
krnl_load_cnt_g mov 0,krnl_t2
jmp #krnl_inc_pc ' next instruction

' loads an address into a register
' the long that follows has 2 arguments
'
' 31 23 22 16 15 0
' +----------+-----+--------+
' | Addr_reg | 0 | cnt |
' +----------+-----+--------+
krnl_load_adr rdlong krnl_t1,krnl_pc
mov krnl_t2,krnl_t1
shr krnl_t1,#23 ' address of destination register!
movd krnl_load_adr_g,krnl_t1 ' sets dest address
and krnl_t2,krnl_cnt_ofsmsk
add krnl_t2, #16 ' adjusts for real address
krnl_load_adr_g mov 0,krnl_t2
jmp #krnl_inc_pc ' next instruction

fit

' stack space for LMM program
c4_lmm_stack long 0, 0, 0, 0, 0, 0, 0, 0
' LMM program, it is executed from the lmm kernel in c4
' No more than a depth of 8 levels in the stack is allowed
' two sets of registers are available, krnl_r0..krnl_r13
' and k4_a..k4_i
' the use of r0..r13 is encouraged

c4_lmm_start mov k4_d,#72
mov k4_e,#16
mov k4_i,#13
call #c4_wkstrxyn
mov k4_d,#0
mov k4_e,#32
mov k4_i,#14
call #c4_wkstrxyn
mov k4_d,#12*8
mov k4_e,#48
mov k4_i,#15
call #c4_wkstrxyn
mov k4_a,#1
shl k4_a,#28
add k4_a,CNT
waitcnt k4_a,#0 ' lets wait showing the copyright
c4_lmm_mainscreen
call #c4_clrscr
' Fixed messages
mov k4_d,#136
mov k4_e,#0
mov k4_i,#1 ' Freq
call #c4_wkstrxyn
mov k4_d,#196
mov k4_e,#8
mov k4_i,#12 ' Hz
call #c4_wkstrxyn
mov k4_d,#136
mov k4_e,#16
mov k4_i,#2 ' Timer
call #c4_wkstrxyn
call #c4_wkstrxyn
call #c4_drawrect4
c4_lmm_mainnc call #c4_ddotoscis

' displays frequency
or k4_flags, #k_4_INVTEXT
call #krnl_load_adr
long @m_L_cfg_fbase+(k4_i<<23)
mov k4_d, #148
mov k4_e, #8
call #c4_wint5
' Timer

' Mode
call #krnl_load_adr
long @m_B_cfg_mode+(k4_a<<23)
rdbyte k4_a, k4_a
cmp k4_a, #k_CTRL_RBUTTON1 wz
if_z mov k4_i, #6 ' Continuos mode
cmp k4_a, #k_CTRL_RBUTTON2 wz
if_z mov k4_i, #7 ' Continuos mode
cmp k4_a, #k_CTRL_RBUTTON3 wz
if_z mov k4_i, #8 ' Continuos mode

mov k4_d,#148
mov k4_e,#32
call #c4_wkstrxyn
' Display Mode
call #krnl_load_adr
long @m_B_cfg_dmode+(k4_a<<23)
rdbyte k4_a, k4_a
cmp k4_a, #k_CTRL_RBUTTON1 wz
if_z mov k4_i, #9 ' Osci
cmp k4_a, #k_CTRL_RBUTTON2 wz
if_z mov k4_i, #10 ' FFT
cmp k4_a, #k_CTRL_RBUTTON3 wz
if_z mov k4_i, #11 ' FFT 4096

mov k4_d,#148
mov k4_e,#40
call #c4_wkstrxyn
' Display Activity, If Active
andn k4_flags, #k_4_INVTEXT ' Normal text

call #krnl_load_adr
long @m_L_ACT+(k4_a<<23)

call #krnl_load_cnt
long k_ACTMAGIC+(k4_b<<23)

cmp k4_a, k4_b wz
if_z mov k4_i, #16 ' active
if_z mov krnl_r4, #17 ' active
if_nz mov k4_i, #18 ' not active
if_nz mov krnl_r4, #18 ' not active
mov k4_d,#140
mov k4_e,#48
call #c4_wkstrxyn
mov k4_i, krnl_r4
mov k4_d,#140
mov k4_e,#56
call #c4_wkstrxyn ' displays ACTIVE MESSAGE


mov k4_a, CNT
add k4_a, cnt_k4_25fps
waitcnt k4_a, #0

rdbyte k4_a,cnt_k4_key
cmp k4_a,#0 wz
if_z jmp #krnl_jmp
long @c4_lmm_mainnc

test k4_a,#k_KMNEXT wc
if_c jmp #krnl_jmp
long @c4_lmm_config

test k4_a,#k_KMPREV wc
if_c jmp #krnl_jmp
long @c4_lmm_config
' Verify for STOP and RUN keys
call #c4_getkey ' consumes key
jmp #krnl_jmp
long @c4_lmm_mainnc

{ Config management
Displays config and allows to change values
Changed values cannot be cancelled !!

}
c4_lmm_config call #c4_getkey ' consumes key
mov k4_a,#0
call #krnl_load_adr
long @m_B_cfg_curr+(k4_b<<23)
wrbyte k4_a,k4_b ' sets current config panel to 0, initial
' loads pointer to panel table
call #krnl_load_adr
long @cnt_w_cfgtbl+(krnl_r4<<23)
c4_lmm_cfg_clr
call #c4_clrscr
c4_lmm_cfg_loop
rdword krnl_r0, krnl_r4 ' loads pointer to panel
call #krnl_load_cnt
long (krnl_r1<<23)+$ffff
cmp krnl_r0, krnl_r1 wz
if_z sub krnl_pc, #($-c4_lmm_mainscreen+1)*4 ' returns to main screen if end of menu reached

call #c4_w_show ' shows control form
' waits for key
call #c4_getkey
rdword krnl_r0, krnl_r4 ' loads pointer to panel

' key was pressed, process key
test k4_a,#k_KMNEXT wc
if_c add krnl_r4, #2 ' increments pointer to next entry in panel table
if_c jmp #krnl_jmp
long @c4_lmm_cfg_clr

test k4_a,#k_KMPREV wc
if_c sub krnl_r4, #2 ' decrements pointer to prev entry in panel table
if_c jmp #krnl_jmp
long @c4_lmm_cfg_clr

test k4_a,#k_KMDOWN wc
if_c call #c4_w_incwptr ' increments pointer to next entry in panel table
if_c sub krnl_pc, #($-c4_lmm_cfg_loop+1)*4

test k4_a,#k_KMUP wc
if_c call #c4_w_decwptr ' increments pointer to next entry in panel table
if_c sub krnl_pc, #($-c4_lmm_cfg_loop+1)*4

test k4_a, #k_KUP wc
if_nc add krnl_pc, #(c4_lmm_cfg_k5-1-$)*4 ' cheap jump

call #c4_w_getselptr ' gets pointer of selected widget
rdword k4_a,krnl_r0
and k4_a, #$f0
cmp k4_a, #k_CTRL_INT5 wz ' if it is a number
if_z call #c4_w_addtovar
cmp k4_a, #k_CTRL_RBUTTON wz ' if it is a radio
if_z call #c4_w_setradio

c4_lmm_cfg_k5 test k4_a, #k_KDOWN wc
if_nc add krnl_pc, #(c4_lmm_cfg_k6-1-$)*4 ' cheap jump

call #c4_w_getselptr
rdword k4_a,krnl_r0
and k4_a, #$f0
cmp k4_a, #k_CTRL_INT5 wz
if_z call #c4_w_subtovar
cmp k4_a, #k_CTRL_RBUTTON wz
if_z call #c4_w_setradio

c4_lmm_cfg_k6
jmp #krnl_jmp
long @c4_lmm_cfg_loop




Enjoy.

Ale
04-14-2009, 10:08 PM
He Jay I was wondering if you saw this ? (And what do you think of it http://forums.parallax.com/images/smilies/smile.gif ? )

Ale

Cluso99
04-15-2009, 07:12 AM
Ale - I have been watching this http://forums.parallax.com/images/smilies/smile.gif

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Links to other interesting threads:

· Home of the MultiBladeProps: TriBladeProp (http://forums.parallax.com/showthread.php?p=786418), SixBladeProp (http://forums.parallax.com/showthread.php?p=780033), website (Multiple propeller pcbs) (http://bluemagic.biz/cluso.htm)
· Single Board Computer:·3 Propeller ICs·and a·TriBladeProp board (ZiCog Z80 Emulator) (http://forums.parallax.com/showthread.php?p=790917)
· Prop Tools under Development or Completed (Index) (http://forums.parallax.com/showthread.php?p=753439)
· Emulators: Micros eg Altair, and Terminals eg VT100 (Index (http://forums.parallax.com/showthread.php?p=778427))
· Search the Propeller forums (via Google) (http://search.parallax.com/search?site=parallax&client=parallax&output=xml_no_dtd&proxystylesheet=parallax&proxycustom=<HOME/>&ie=&oe=&lr=)
My cruising website is: ·www.bluemagic.biz (http://www.bluemagic.biz)·· MultiBladeProp is: www.bluemagic.biz/cluso.htm (http://www.bluemagic.biz/cluso.htm)

Ale
04-15-2009, 06:50 PM
Cluso: But you did not see it work! because it does http://forums.parallax.com/images/smilies/wink.gif. I'm so proud of that code (the whole thing) that I forgot to make the real piece of electronic work :-(. Anybody knows why those Amidon toroidal cores are not good to make a transformer ? :-( :-(

nutson
04-15-2009, 08:17 PM
Ale, could you elaborate on the the project this code is taken from? Reason; the comments suggest it is from·a·test and measurement application, ref "oscilloscope display" etc. FFT is very interesting, basic for any type of spectrum analyzer.

For quite some time I·have wanted to build·a test and measurement system with multiple props each generating /·measuring certain signals (DC, LF analog, HF analog, digital, protocol,·TV). Comparable to this·project ·http://www.heise.de/ct/projekte/machmit/ctlab/wiki. But being a propeller user with props of course. I can handle all the hardware detail, but as I am·less of a software person·I cannot decide on two important·software aspects:
- the GUI: how to control·generated·signals and control measurement result display? (Try to) use a PC application like in the mentioned project "NI Labview"? There is some·good software around (like Virtins Multi-instrument 3.1) that uses a PC soundcard as a measurement device. Use a prop with VGA and mouse·to display and alter parameters?·Use Viewport?·Use Femtobasic (text oriented, but with good automation possibilities)?
- how to display oscilloscope type·signals. I have·a number of FPGA4FUN Flashy modules available (100Mhz, 8 bit sampling) but how to display the results? Could a prop (or multiple props) handle 4 traces of (graphics) oscilloscope display? I can·use the·FPGA needed for·the Flashy modules to generate a VGA signal (have done some experiments already), but that is quite inflexible. Transport the data to a PC and display it there (viewport again?). · Hanno had a T&M application in the pipeline "dreamkit",·hoped this would come with general purpose·GUI software, but this seems to evolve into the "propscope".

Would appreciate any thoughts on·this.

Nico Hattink·

Ale
04-16-2009, 02:52 AM
nutson: It all depends on how many MPS you want, which are you tolerable dead times and what do you want to do with the signals.

Just to display them at 60 Hz is not a problem, even 4 of them (some 200 or so samples). If you want something fancy like what real DSO do (aka digital phosphor or similar) forget it because you do not even have more than3 shades of the same color available!. The point here is the dead time you can tolerate.

FFT is not a problem, just see the article I wrote on propeller.wikispaces.com/FFT (http://propeller.wikispaces.com/FFT). I tested it with a real propeller too http://forums.parallax.com/images/smilies/smile.gif. It works.

My simple (very) GUI does not allow more than some simple widgets (numbers and radio buttons and text) with max/min values and increment prefixed (to be used with a rotary encoder). I can post the code of a simple oszi with FFT for VGA ready-to-use if you are still interested.

nutson
04-16-2009, 03:22 AM
I would me delighted if you would post your code for a basic VGA oscilloscope. My coding skills are such that I can understand and modify a example, but not good enough to do it all from scratch. You may remember I am working with FPGA's, my goal would be to have the FPGA acquire preprocess the ADC data, and have the prop display them.

Ale
04-16-2009, 03:23 PM
Here is the FFT example.

You will need an ADC (any will do) just modify the hardware accordingly to accept the data nd you are done.

If I find a picture of this I'll post it.

Have fun.

nutson
04-16-2009, 11:43 PM
Jay, sorry for hijacking your post, will not post here more.

Ale, many thanks, just got it working (without a DAC). Just inserted the CNT value where you do the INA in the ADC routine.