OPL Challenge

Feel free to discuss any Organiser II related topic here
User avatar
MartinReid
Posts: 97
Joined: Wed Jan 27, 2021 3:44 pm

Finalised HLog

Post by MartinReid »

Dear Gary

Yes that's right; the values are set permanent until changed by the user. Except TXT:, CSn:, Bgn: and End: all values are retained after a Log: or retrieved from the last record saved when you re-enter the programme after using the Organiser for something else.

When values change then a user can edit the current or re-enter a new as desired. As you say this could be anything as long as the maximum length of the values (as set out in the instructions) is retained to ensure they appear correctly in the print out.

Have you tried using the print option? I can recommend ORG-Link [File Relay] into Windows Notepad... Use Notepad, Format, Font - to Courier New (Bold) works really great.

I can MAKE you an updated programme pack when you are ready

Always sincere
Martin
User avatar
MartinReid
Posts: 97
Joined: Wed Jan 27, 2021 3:44 pm

Re: OPL Challenge

Post by MartinReid »

Lostgallifreyan wrote: Thu Oct 21, 2021 2:14 am Martin, I found some notes I made on machine code and service calls, and the first part of those is posted below in the 'code' block. It's no substitute for a proper guide but it's what I wrote when in the same position you're in now, when I needed a condensed form that told me the most vital stuff.

The two examples don't do much but they're safe to use, and the form they take will be similar for any service the system offers, as is the way that OPL sets them up and calls them. More useful will be the preamble that describes registers. There is no mention of the stack though, but these two examples will be good enough to start with.

Reading Jaap's pages on machine code reference will cover most if not all you'll need to know. I found those notes more useful than a long guide, because they make it easy to pick something that looks useful and try it. The stuff here, below, will help you make them work with OPL.

Code: Select all

Operating system services are machine code programs stored in ROM. Many are accessed by OPL commands and functions, but many of the best ones are not.
All system service calls begin with instruction SWI, 'software interrupt', hex byte $3F, immediately followed by a byte indexing the required service.
The next byte is where the program resumes when the system service has finished. This is usually RTS, 'return from subroutine', hex byte $39, in this
case return to OPL because an OPL function USR (or USR$) is used to call the machine code that calls the service. (Note that these are functions, they
pass data back to the program, but commands do not, they only direct a specific action).

Most services need parameters to define the context for their use. There are registers called A, B and X which are usually enough to pass information
to a service, with six 'scratch registers' UTW_S0 to UTW_S5, at address range $41-$4C as extra locations. Larger data can be placed in the 'runtime
buffer' RTT_BF, a 'leading byte-count string' at address range $2188-$2287 with length byte RTT_BL at $2187. System services may use these locations
to pass data out as well as in. A register should be assumed destroyed unless the service specifically uses it to pass back data.

An error sets its code in register B and sets the 'carry' flag, which may hold a previous state, so test it only after a service that uses it.

The OPL function USR calls machine code at the address given in the first of two arguments, and passes an integer into the D register with the other.
The D register is a word, and the A and B byte registers are passed as D, in the form A*256+B. The service context determines which scheme is valid.
The X register is also a word, and must contain the output to be passed back to OPL from the USR function. (USR$ passes the address to a string.)

==========================================================================================================================================================

013 0D  BZ$ALRM
INPUT:  None.
OUTPUT: None.
        D,X=trashed
        UTW_Sx=preserved
DESCRIPTION
        Gives the noise used by ALARM. Note that keyboard interrupts are disabled temporarily.
EXAMPLE:
        SWI     BZ$ALRM
ERRORS: None.

ALARM:
LOCAL C%(2)
C%(1)=$3F0D :rem  SWI BZ$ALRM
C%(2)=$3900 :rem  RTS (back to OPL)
USR(ADDR(C%),0)

==========================================================================================================================================================

118 76  UT$SMUL
INPUT:  D=Signed integer
        X=Signed integer
OUTPUT: D=High bytes of 4-byte signed product.
        X=Low bytes of 4-byte signed product.
DESCRIPTION:
        2-byte by 2-byte signed integer multiply routine.  Multiplies  D  by  X
        putting  the  product  back into D and X.  The more significant word of
        the product goes into D.
EXAMPLE:
        LDX     SIGNED_MULTIPLIER
        LDD     SIGNED_MULTIPLICAND
        SWI     UT$SMUL
        TST     A               ; test the most significant byte
        BMI     NEGATIVE_PRODUCT
ERRORS: None.

MULTIPLY:
LOCAL C%(5)
C%(1)=$0000 :rem  Input for D register
C%(2)=$01CE :rem  NOP,LDX
C%(3)=$0000 :rem  Input for X register
C%(4)=$3F76 :rem  SWI UT$SMUL
C%(5)=$3900 :rem  RTS (back to OPL)
INPUT C%(1)
INPUT C%(3)
PRINT USR(ADDR(C%())+2,C%(1))
GET

------------------------------------------------------------------------------

Note: Don't confuse UT$SMUL (or UT$UMUL or MT$FMUL) with the basic instruction MUL, as used below.

MULTIPLY:
LOCAL C%(2),M%,N%
C%(1)=$3D18
C%(2)=$3900
INPUT M%
INPUT N%
PRINT USR(ADDR(C%()),M%*256+N%)
GET

==========================================================================================================================================================
Lostgallifreyan
Just a quick update while I'm logged in...
I'm working through your notes and am trying to read Jaaps Machine Code Tutorials so will add more later..

In the mean time my 1st efforts...

(1) there is an Missing External C% error in... 013 0D BZ$ALRM
ALARM:
LOCAL C%(2)
C%(1)=$3F0D :rem SWI BZ$ALRM
C%(2)=$3900 :rem RTS (back to OPL)
USR(ADDR(C%),0)

>>>> USR(ADDR(C%()),0)

(2) I need to go again with... 118 76 UT$SMUL
I managed to crash my LZ64 with my first attempt...
TRAP 7EE1
9ACE
I thought I had carefully typed and rechecked the code before running; but maybe I've mistyped something. I'll have another go later..

Always sincere
Martin
hawsey
Posts: 42
Joined: Fri Jul 02, 2021 12:34 am

Re: OPL Challenge

Post by hawsey »

hawsey wrote: Fri Oct 15, 2021 9:10 pm
MartinReid wrote: Tue Oct 05, 2021 12:48 pm

Gary.. if you are reading this then I'm going to implement this 'FromLst$' function in HamLog. So the user can select their values from a given list. With this in mind I will be looking a heads up on which of the 'log' entries can be 'predicted' and what 'values' should be offered as a selection...

Csign: No.. individual entry
Htz: ?
Mode: ?
Power: ?
Signal: ?

Again thanks for your thoughts.
Always sincere
Martin
Hi Martin

For values for power
Foundation licence limit is 10 Watts
Intermediate is 50 Watts
Full is 400 Watts
So adding these values would be helpful please.
Also for modes, FT8 and DMR could be added as both are popular ( with some)
As for frequencies I'm not sure but some higher frequencies are missing, the frequency part could be replaced with band measured in metres which would possibly simplify things, what do you think? 2M(eters) is 144Mhz for example. Also there are bands like 23cm which is 1.2 Ghz and others.
Thank you
Regards
Gary
User avatar
MartinReid
Posts: 97
Joined: Wed Jan 27, 2021 3:44 pm

Ready to go...

Post by MartinReid »

Thanks Gary... All done... Ready to go...
User avatar
Lostgallifreyan
Posts: 27
Joined: Fri Jun 11, 2021 2:52 pm

Re: OPL Challenge

Post by Lostgallifreyan »

Those programs definitely work. Did you put the entire text in a PROG editor session? If so that would break it because the first line is the procedure name, extracted from the file on normal import so the editable text begins with LOCAL... If that had got displaced by direct text entry (in the Organiser's PROG editor), then LOCAL would not be the first thing, and C% would not be declared, hence the system thinking it must be external.

A real external would be used like the floating point N in this:

Code: Select all

ARCOSINE:(N)
RETURN DEG(ATAN(SQR(ABS(1-(N*N)))/N))
That might be useful in the calculator as Arcosine:(N) because it hasn't got one.

When I start a procedure I never add anything to the top line unless it IS an external reference, then GLOBAL (if any) always begins the first new line, then LOCAL after any GLOBAL is done, then any hardware initialisation that is needed. Organisers tend to panic over anything else.

The most reliable way to transfer those machine code examples is to copy/paste to empty *.txt (make sure it is NOT unicode!), then rename as *.OPL, then transfer to the Organiser and translate it there, then run it. Translation on a PC then transferring the *.OB3 also works.
User avatar
Lostgallifreyan
Posts: 27
Joined: Fri Jun 11, 2021 2:52 pm

Re: OPL Challenge

Post by Lostgallifreyan »

Martin, I think you might have found an error in the alarm proc. I think you're right to consider ADDR(C%()) to get the address of the array. My other examples have it that way, and I'm not sure why that one doesn't. It may have been added to the notes file from dubious memory and not tested.

The more useful SWI examples in that EditFile proc in the EVENT post on this forum definitely work, they're the most recently written and tested, and they do it with the () after the array name too.
Post Reply