# Assembler for Padauk microcontroller

### What is this?

I just started to learn Padauk microcontrollers and I did not find a pure assembler. I decided to write one. This is not a competitor of SDCC or other more advanced developent tools and programming languages but sometimes less is more. I tried to keep it as simple as possible make it easy to learn. If you have some assembly programming background you will learn to use it a few minutes. The syntax is very simple.
Keep in mind this is the first assembler I wrote, very experimental, not fully tested...
At this moment PFS154 is the only supported microcontroller. Maybe I will add PFS173 later. I don't plan to create assembler for OTP (One-Time Programmable) microcontrollers.

### How to use?

You can write the source code in any plain text editor. Save the file as "a.asm" at the same folder where pfs154.py located. The assembler is written in Python 3. You can download Python for free. Open the pfs154.py file and click Run > Run Module or just hit F5.
The assembler will create a parsed.temp file (you can delete it) and an a.hex file. For Windows users if you don't want to download Python there is an PFS154.exe in downloads, you may run that in cmd. You can download the a.hex to PFS154 microcontroller with your free-pdk programmer.
`easypdkprog -n PFS154 write a.hex`

### Syntax

I tried to stick to the syntax you can find in PFS154 data sheet as much as possible. You should learn only a very few extra syntax. The assembler is case insensitive, lowercase and uppercase letters are threated equivalent.

Segments

There are 2 segments, .var for variables and .rom for code. .var is optional but if exists it should be before .rom

`

     .var
    	; put variables here

     .rom
    	; put code here

`

Declare variables

Padauk use M keyword for SRAM where we store our variables. But there is a very similar space called IO. This is for Special Function Registers (SFR). In my assembler we have to specify with M or IO prefix where we store our variable. First comes the varible name then the address with M or IO prefix, a 2 digit hex number for address and 'h' in the end represents its hex number. The good news you don't have to declare the SFR-s, I already declared them in program. You can find the list of already declared SFRs in pfs154.py source code after "var =" line.

`

     .var
        myvar  M2Ah
        clkmd  IO03h

`

Bit declaration

You can declare bits also. Flag bits are already declared like so

`

     .var
        mybit M14h.5
        Z IO00h.0	 ; Flag register Zero bit
        C io00h.1    ; Flag register Carry bit

`

If you have a declared varible like above the myvar, you can access any bit using the myvar.n syntax without declaring the bit. Port registers are already declared, PA, PB... If you want to access a bit for example PA.0 you can use it in the code - no need to declare it.

Code syntax

Labels must end with colon. (label:)
Immediate (literal, constant) values MUST start with #.
After .orgxxxh directive the code will start at the provided address. Only 3 digit hex number accepted here. Interrupt starts at 10h address so it is usefull here.
After call and goto you may use label or direct address. For calibration we have to call 0x7ed to return the calibration value. You can use the call $xxxh syntax, call $7edh in this case for IHRC calibration.

### Code examples

Start-up code

`

     .rom
    	wdreset

    	mov  a,#9ch     ; setup clkmd, IHRC/64, disable watchdog
    	mov  clkmd,a

    	call $7edh      ; clock calibration
    	mov  ihrcr,a

    	call $7eeh      ; bandgap tuning
    	mov  bgtr,a

    	mov  a,#40h     ; set stack pointer 0x40 = 64
    	mov  sp,a

`

I do recommend always set up the Clock Mode (clkmd), do the IHRC calibration, bandgap tuning and set up the stack pointer in the beginning of your code.

LED blinker

1sec on/off state will alter.

`

     .var
    	t1  M00h
    	t2  M01h
    	t3  M02h

     .rom
    	wdreset
    	mov   a,#34h
    	mov   clkmd,a
    	call  $7edh
    	mov   ihrcr,a
    	call  $7eeh
    	mov   bgtr,a
    	mov   a,#40h	;0x40 = 64
    	mov   sp,a
    	set1  pac.0
    	clear t1
    	mov   a,#40
    	mov   t2,a
    	mov   a,#1
     lab1:
    	xor   pa,a
    	call  wait1s
    	goto  lab1

     wait1s:
    	pushaf
    	clear t1
    	clear t2
    	mov   a,#24
    	mov   t3,a
     w1:
    	nop
    	nop
    	dzsn  t1
    	goto  w1
    	dzsn  t2
    	goto  w1
    	dzsn  t3
    	goto  w1
    	popaf
    	ret

`

Advanced LED blinker :D

In this example you can see how to use T16 timer and interrupt. 264ms on/off state will alter.

`

     .var
    	t1      M20h
    	t2      M21h

     .rom
    	wdreset
    	goto    main
     .org010h                ; interrupt
    	pushaf
    	mov     a,#1
    	xor     pa,a
    	set0    intrq.2
    	popaf
    	reti

     main:
    	mov     a,#34h
    	mov     clkmd,a
    	call    $7edh
    	mov     ihrcr,a
    	call    $7eeh
    	mov     bgtr,a
    	mov     a,#40h      ; 0x40 = 64
    	mov     sp,a
    	set1    pac.0

    	clear   t1
    	clear   t2
    	stt16   t1

    	set1    integs.4    ; falling edge
    	mov     a, #9fh     ; IHRC, div=64, interrupt change on 15th bit
    	mov     t16m, a

    	set0    intrq.2     ; clear T16 irq flag
    	set1    inten.2     ; enable T16 interrupt

    	engint

     loop:
    	nop
    	nop
    	nop
    	goto    loop

`

### Downloads

PFS154 assembler
Note: source file must be named a.asm and it should be in the same folder where pfs154.py (or pfs154.exe) located.