Full Version : Lanconelli's Dallas DS1621 Thermometer (ASM)
avr >>HOME & TIME & TEMPERATURE PROJECTS >>Lanconelli's Dallas DS1621 Thermometer (ASM)


Admin3- 04-19-2006
Claudio Lanconelli's Thermometer Project using Dallas DS1621
Sends Tempurature out RS232 Port

CODE

;FILE: MACRO.INC
.LISTMAC



.MACRO  ADDI    

subi @0, -(@1)

.ENDMACRO



;skip next instruction if not equal to zero

.MACRO skipne                  

.SET    _skipne = PC+2

brne    _skipne

.ENDMACRO



;skip next instruction if carry set

.MACRO skipcs                  

.SET    _skipcs = PC+2

brcs    _skipcs

.ENDMACRO



;skip next instruction if carry clear

.MACRO skipcc

.SET    _skipcc = PC+2

brcc    _skipcc

.ENDMACRO



;skip next instruction if equal to zero

.MACRO  skipeq

.SET    _skipeq = PC+2

breq    _skipeq

.ENDMACRO



;skip next instruction if lower

.MACRO skiplo                  

.SET    _skiplo = PC+2

brlo    _skiplo

.ENDMACRO



;skip next instruction if half carry set

.MACRO skiphs                  

.SET    _skiphs = PC+2

brhs    _skiphs

.ENDMACRO



;skip next instruction if half carry clear

.MACRO skiphc

.SET    _skiphc= PC+2

brhc   _skiphc

.ENDMACRO



;skip next instruction if T set

.MACRO skipts                  

.SET    _skipts = PC+2

brts    _skipts

.ENDMACRO



;skip next instruction if T clear

.MACRO skiptc                  

.SET    _skiptc = PC+2

brtc    _skiptc

.ENDMACRO



;skip next instruction if minus

.MACRO skipmi

.SET    _skipmi = PC+2

brmi    _skipmi

.ENDMACRO



;skip next instruction always

.MACRO skipnext

.SET _skipnext = PC+2

rjmp _skipnext

.ENDMACRO



;wait two cycles but waste only one instruction

.MACRO  doublenop

.SET    _doublenop = PC+1

rjmp    _doublenop

.ENDMACRO



;compare Port bit with T, and branch to @2 if are not equal

.MACRO cpeqPortBit

sbic @0,@1

.SET _cpPortBit1 = PC+3

rjmp _cpPortBit1

brts @2

.SET _cpPortBit0 = PC+2

rjmp _cpPortBit0

brtc @2

.ENDMACRO



;compare Port bit with T, and branch to @2 if are equal

.MACRO cpnePortBit

sbic @0,@1

.SET _cpPortBit1 = PC+3

rjmp _cpPortBit1

brtc @2

.SET _cpPortBit0 = PC+2

rjmp _cpPortBit0

brts @2

.ENDMACRO



;compare Register bit with T, and branch to @2 if are not equal

.MACRO cpeqRegBit

sbrc @0,@1

.SET _cpRegBit1 = PC+3

rjmp _cpRegBit1

brts @2

.SET _cpRegBit0 = PC+2

rjmp _cpRegBit0

brtc @2

.ENDMACRO



;compare Register bit with T, and branch to @2 if are equal

.MACRO cpneRegBit

sbrc @0,@1

.SET _cpRegBit1 = PC+3

rjmp _cpRegBit1

brtc @2

.SET _cpRegBit0 = PC+2

rjmp _cpRegBit0

brts @2

.ENDMACRO


;***************************************************************************

;* THERMOMETER.ASM

;*

;* Read temperature from DS1621 and send it to RS232

;* AVR MINI THREADS v.1.02

;* ---> nanoKernel for the AVR AT90S1200

;*

;* Copyright (c) 1998 by Claudio Lanconelli

;* e-mail: lanconel@cs.unibo.it

;* WWW: http://www.cs.unibo.it/~lanconel

;*

;/ This program is free software; you can redistribute it and/or           //

;/ modify it under the terms of the GNU  General Public License            //

;/ as published by the Free Software Foundation; either version2 of        //

;/ the License, or (at your option) any later version.                     //

;/                                                                         //

;/ This program is distributed in the hope that it will be useful,         //

;/ but WITHOUT ANY WARRANTY; without even the implied warranty of          //

;/ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       //

;/ General Public License for more details.                                //

;/                                                                         //

;/ You should have received a copy of the GNU  General Public License      //

;/ along with this program (see COPYING);     if not, write to the         //

;/ Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. //

;***************************************************************************



.DEVICE AT90S1200



.include "macro.inc"

.include "1200def.inc"





;In questo esempio utilizzo solo 2 thread.

;-il primo (principale) controlla in polling lo stato di un pulsante (PinB-0), e

; quando viene premuto accende un Led (PortD-0) e inizia una conversione di

; temperatura del DS1621, attende che finisca e trasmette il risultato sulla

; seriale settata a 1200,n,8,1 (divisore timer calcolato per quarzo 3.6864 MHz)

;-il terzo (serial driver) attende richieste di output dal thread1 e quando ne ha trasmette

; un bit alla volta su interrupt del timer.



;N.B. il DS1621 comunica tramite bus seriale I2C, i cui segnali vengono implementati sulla

;     portaB (PortB-7 --> SDA, PortB-6 --> SCL). Le routine I2Cbus sono tratte dalle app.note

;     dell'Atmel (avr300).

;     I segnali sono gli stessi utilizzati per la programmazione in-circuit tramite PonyProg,

;     la programmazione non da` alcun problema con resistenze di pull-up I2C di 4K7.



;In this example I use only two threads.

;-the first (main thread) polls the status of the key (PinB-0). When the key is

; pressed switch on the Led (PortD-0) and start temperature conversion within

; the DS1621. Then it wait for the end of the conversion, read the temperature,

; and transmit it over the serial line (1200,n,8,1) with a crystal of 3.6864MHz.

;-the third (serial driver) wait for a request from thread1, and transmit

; a bit at a time (a timer interrupt for each bit) over serial line



;The DS1621 communicate over the I2C Bus. I2C Bus routines are taken from Atmel

; app.note (avr300). PortB-7 --> SDA, PortB-6 --> SCL.

; The same pins are used for the ISP programming with PonyProg.



.CSEG



;***************************************************************************

;* VARIABLE ASSIGNEMENTS

;***************************************************************************



.def SaveThr1Status = r0    ;status copy for thread 1

.def SaveThr2Status = r1;status copy for thread 2

.def SaveThr3Status = r2;status copy for thread 3

.def SaveStatus = r3;status copy for interrupts



.def Temperatura = r4



.def SerNbit  = r16;serial bit to transmit

.def SerData  = r17;serial data byte to transmit

.def TmrDivisor = r18



.def i2cdelay = r19; Delay loop variable

.def i2cdata  = r20; I2C data transfer register

.def i2cadr  = r21; I2C address and direction register

.def i2cstat  = r22; I2C bus status register



.def    Main1  = r23;Temp variable used by main program

.def MiscFlags = r31;threads status flags + signal flags



;flags bit definition

.equ Thread1Status = 0; 1 --> ready, 0 --> waiting

.equ Thread2Status = 1

.equ Thread3Status = 2

.equ Thread1Signal = 3

.equ Thread2Signal = 4

.equ Thread3Signal = 5

.equ SerRequest = 6



.equ THRSTATUSMASK =  7

.equ SIGNALMASK =  112





;***************************************************************************

;* Port Pin Assignements

;***************************************************************************



;port D bit definitions

.equ Led1 = 0;out

.equ Led2 = 1;out



;port B bit definitions

.equ Key1 = 0;in (pullup)

.equ SerTx = 4;out



.equ SCLP = 6; SCL Pin number (port D)

.equ SDAP = 7; SDA Pin number (port D)



;************************

;* Constants (not change)

;************************



.equ b_dir = 0  ; transfer direction bit in i2cadr



.equ i2crd = 1

.equ i2cwr = 0





;***************************************************************************

;* VECTORS

;***************************************************************************



 rjmp    RESET  ;Reset Handle

 rjmp    INT0DRV  ;Ext. interrupt request 0

 rjmp    TIMERDRV;Timer





;***************************************************************************

;*

;* MAIN PROGRAM

;*

;***************************************************************************

;* INITIALIZATION

;***************************************************************************



RESET:  

 ldi Main1, 0b01111011;set port D bits to outputs (INT0 as an input)

 out DDRD, Main1

 ldi Main1, 0b00000111;preset  output state (activate INT0 pull-up)

 out PortD, Main1

 ldi Main1, 0b00010000;set port B to inputs (SCL e SDA = 0), SerTx to output

 out DDRB, Main1

 ldi Main1, 0b00101111;turn on pullups on inputs (SCL e SDA = 0)

 out PortB, Main1



 ldi Main1, 5

 out TCCR0, Main1;set prescaler to CK/1024

 ldi Main1, 32+2

 out MCUCR, Main1;enable sleep idle mode (ext int on falling edge)

 ldi Main1, 2

 out TIMSK, Main1;enable timer interrupt

 ldi Main1, 64

 out GIMSK, Main1;enable external interrupt



 ldi Main1, 256-3;load Timer Counter with 3 count to interrupt (1200bps)

 out TCNT0, Main1



 ldi MiscFlags,THRSTATUSMASK



 sei  ;enable interrupts



 in SaveThr1Status,SREG;initialize status (interrupts enabled in all thread)

 mov SaveThr2Status,SaveThr1Status

 mov SaveThr3Status,SaveThr1Status

 

;=====================================

;THREAD 1

; main loop

THR1LOOP:

;test if the key is pressed

 sbic PinB,Key1

 rjmp L001

 cbi PortD,Led1;switch the led on



;start I2C communication

;the periferal is located at 0x90 + offset, where offset is given by A0,A1,A2 (address pin)

;for this example the address is 0x9E (A0 = +5V, A1 = +5V, A2 = +5V)



;**** Write data => Adr(9E) = 0xEE ****;EE --> Start conversion



 ldi i2cadr,$9E+i2cwr; Set device address and write

 rcall i2c_start; Send start condition and address



 ldi i2cdata,$EE; Write command byte

 rcall i2c_do_transfer; Execute transfer



 brcs ERRNOACK



 rcall i2c_stop



;========= end conversion cycle

READCONFIG:

;permit other thread to exececute

 sbr MiscFlags, EXP2(Thread1Signal)

 rcall WAIT1



;**** Write data => Adr(9E) = 0xAC ****;AC --> Read status/configuration register



 ldi i2cadr,$9E+i2cwr; Set device address and write

 rcall i2c_start; Send start condition and address



 ldi i2cdata,$AC; Write command byte

 rcall i2c_do_transfer; Execute transfer



 brcs ERRNOACK



;**** Read data => i2cdata = Adr(9E) ****



 ldi i2cadr,$9E+i2crd; Set device address and read

 rcall i2c_rep_start; Send repeated start condition and address



 sec  ; Set no acknowledge (read is followed by a stop condition)

 rcall i2c_do_transfer; Execute transfer (read)



 rcall i2c_stop; Send stop condition - releases bus



 sbrs i2cdata,7; test DONE bit in status/configuration register

 rjmp READCONFIG



;====== Read temperature command

;**** Write data => Adr(9E) = 0xAA ****;AA --> Read temperature



 ldi i2cadr,$9E+i2cwr; Set device address and write

 rcall i2c_start; Send start condition and address



 ldi i2cdata,$AA; Write command byte

 rcall i2c_do_transfer; Execute transfer



 brcs ERRNOACK



;**** Read data => i2cdata = Adr(9E) ****



 ldi i2cadr,$9E+i2crd; Set device address and read

 rcall i2c_rep_start; Send repeated start condition and address



 clc

 rcall i2c_do_transfer

 mov Temperatura,i2cdata;temperature MSByte, we ignore the other byte



 sec  ; Set no acknowledge (read is followed by a stop condition)

 rcall i2c_do_transfer; Execute transfer (read)



 rcall i2c_stop; Send stop condition - releases bus





;===== Transmit the temperature over the serial line

 mov SerData,Temperatura

 sec  ;transmit most significant digit

 rcall BIN2ASCII



 sbr MiscFlags, EXP2(SerRequest)

 sbr MiscFlags, EXP2(Thread3Signal);send the request to RS232 thread

 rcall WAIT1



 mov SerData,Temperatura

 clc  ;transmit least significant digit

 rcall BIN2ASCII



 sbr MiscFlags, EXP2(SerRequest)

 sbr MiscFlags, EXP2(Thread3Signal)

 rcall WAIT1



;====== done

 rjmp THR1LOOP



L001:

 sbi PortD,Led1;switch off the led



 sbr MiscFlags, EXP2(Thread1Signal)

 rcall WAIT1

 rjmp THR1LOOP



ERRNOACK:;transmit "err" over the serial line

 ldi SerData,101;'e'

 sbr MiscFlags, EXP2(SerRequest)

 sbr MiscFlags, EXP2(Thread3Signal)

 rcall WAIT1



 ldi SerData,114;'r'

 sbr MiscFlags, EXP2(SerRequest)

 sbr MiscFlags, EXP2(Thread3Signal)

 rcall WAIT1



 ldi SerData,114;'r'

 sbr MiscFlags, EXP2(SerRequest)

 sbr MiscFlags, EXP2(Thread3Signal)

 rcall WAIT1



 rjmp THR1LOOP



;-----------------

;converts a binary byte to ASCII char

;

;if Carry == 1, most significant nibble

;otherwise      less significant nibble

;-----------------

BIN2ASCII:

 brcc DIGIT0

 swap SerData

DIGIT0:

 andi SerData,15

 cpi SerData,10

 brlo DIGDEC

 addi SerData,(65-10);'A'

 ret

DIGDEC:

 addi SerData,48;'0'

 ret



;-----------------

WAIT1:

;save status before switch to another thread

 in SaveThr1Status,SREG

 sbrs MiscFlags, Thread1Signal;check for reeceived signal

 cbr MiscFlags, EXP2(Thread1Status);thread1 in wait state

 cbr MiscFlags, EXP2(Thread1Signal);reset signal

 rjmp SCHEDULER2

THR1WAKEUP:

 ret





;=================================

;THREAD 2 (do nothing)

; main loop

THR2LOOP:

;thread 2 WAIT

;we can't do a separate Wait subroutine for every thread. Note that

;the stack is hardware, and not accessible.

;save status before switch to another thread

 in SaveThr2Status,SREG

 sbrs MiscFlags, Thread2Signal;check for received signal, if we have already

     ;received the signal don't go sleep

 cbr MiscFlags, EXP2(Thread2Status);thread2 in wait state

 cbr MiscFlags, EXP2(Thread2Signal)

 rjmp SCHEDULER3

THR2WAKEUP:

 rjmp THR2LOOP





;===================================

;THREAD 3: SERIAL OUTPUT DRIVER

; main loop

THR3LOOP:

;thread 3 WAIT

;save status before switch to another thread

 in SaveThr3Status,SREG

 sbrs MiscFlags, Thread3Signal;check for received signal

 cbr MiscFlags, EXP2(Thread3Status);thread3 in wait state

 cbr MiscFlags, EXP2(Thread3Signal)

 rjmp SCHEDULER1

THR3WAKEUP:

;testa SerRequest per capire se siamo stati risvegliati dal Thr1 o dal Timer

 sbrc MiscFlags, SerRequest

 rjmp THR3_L1



;siamo stati risvegliati dal timer, controlliamo se ci sono dati da trasmettere

 tst SerNBit    ;se zero non fa niente

 breq THR3LOOP



 dec SerNBit

 breq THR3_TXEND  ;se zero tx stop e FINITO



 cpi SerNBit,9  ;tx start

 breq THR3_TX0

THR3_TXDATA:

 lsr SerData    ;trasmette il prossimo bit (nel carry)

 brcc THR3_TX0

THR3_TX1:

 cbi PortB,SerTx

 rjmp THR3LOOP

THR3_TX0:

 sbi PortB,SerTx

 rjmp THR3LOOP

THR3_L1:

;nuova richiesta (dal Thr1)

 cbr MiscFlags, EXP2(SerRequest)

 ldi SerNBit,10  ;tx 10 bits: 1start + 8dati + 1stop

 rjmp THR3LOOP

THR3_TXEND:

 sbr MiscFlags, EXP2(Thread1Signal);wakeup thread 1

 rjmp THR3_TX1





;***************************************************************************

;*

;* FUNCTION

;* i2c_hp_delay

;* i2c_qp_delay

;*

;* DESCRIPTION

;* hp - half i2c clock period delay (normal: 5.0us / fast: 1.3us)

;* qp - quarter i2c clock period delay (normal: 2.5us / fast: 0.6us)

;*

;* SEE DOCUMENTATION !!!

;*

;* USAGE

;* no parameters

;*

;* RETURN

;* none

;*

;***************************************************************************



i2c_hp_delay:

ldi i2cdelay,6

i2c_hp_delay_loop:

dec i2cdelay

brne i2c_hp_delay_loop

ret



i2c_qp_delay:

ldi i2cdelay,3;2.333

i2c_qp_delay_loop:

dec i2cdelay

brne i2c_qp_delay_loop

ret





;***************************************************************************

;*

;* FUNCTION

;* i2c_rep_start

;*

;* DESCRIPTION

;* Assert repeated start condition and sends slave address.

;*

;* USAGE

;* i2cadr - Contains the slave address and transfer direction.

;*

;* RETURN

;* Carry flag - Cleared if a slave responds to the address.

;*

;* NOTE

;* IMPORTANT! : This funtion must be directly followed by i2c_start.

;*

;***************************************************************************



i2c_rep_start:

sbi DDRB,SCLP; force SCL low

cbi DDRB,SDAP; release SDA

rcall i2c_hp_delay; half period delay

cbi DDRB,SCLP; release SCL

rcall i2c_qp_delay; quarter period delay





;***************************************************************************

;*

;* FUNCTION

;* i2c_start

;*

;* DESCRIPTION

;* Generates start condition and sends slave address.

;*

;* USAGE

;* i2cadr - Contains the slave address and transfer direction.

;*

;* RETURN

;* Carry flag - Cleared if a slave responds to the address.

;*

;* NOTE

;* IMPORTANT! : This funtion must be directly followed by i2c_write.

;*

;***************************************************************************



i2c_start:    

mov i2cdata,i2cadr; copy address to transmitt register

sbi DDRB,SDAP; force SDA low

rcall i2c_qp_delay; quarter period delay





;***************************************************************************

;*

;* FUNCTION

;* i2c_write

;*

;* DESCRIPTION

;* Writes data (one byte) to the I2C bus. Also used for sending

;* the address.

;*

;* USAGE

;* i2cdata - Contains data to be transmitted.

;*

;* RETURN

;* Carry flag - Set if the slave respond transfer.

;*

;* NOTE

;* IMPORTANT! : This funtion must be directly followed by i2c_get_ack.

;*

;***************************************************************************



i2c_write:

sec  ; set carry flag

rol i2cdata  ; shift in carry and out bit one

rjmp i2c_write_first

i2c_write_bit:

lsl i2cdata  ; if transmit register empty

i2c_write_first:

breq i2c_get_ack; goto get acknowledge

sbi DDRB,SCLP; force SCL low



brcc i2c_write_low; if bit high

nop  ; (equalize number of cycles)

cbi DDRB,SDAP; release SDA

rjmp i2c_write_high

i2c_write_low:  ; else

sbi DDRB,SDAP; force SDA low

rjmp i2c_write_high; (equalize number of cycles)

i2c_write_high:

rcall i2c_hp_delay; half period delay

cbi DDRB,SCLP; release SCL

rcall i2c_hp_delay; half period delay



rjmp i2c_write_bit





;***************************************************************************

;*

;* FUNCTION

;* i2c_get_ack

;*

;* DESCRIPTION

;* Get slave acknowledge response.

;*

;* USAGE

;* (used only by i2c_write in this version)

;*

;* RETURN

;* Carry flag - Cleared if a slave responds to a request.

;*

;***************************************************************************



i2c_get_ack:

sbi DDRB,SCLP; force SCL low

cbi DDRB,SDAP; release SDA

rcall i2c_hp_delay; half period delay

cbi DDRB,SCLP; release SCL



i2c_get_ack_wait:

sbis PINB,SCLP; wait SCL high

   ;(In case wait states are inserted)

rjmp i2c_get_ack_wait



clc  ; clear carry flag

sbic PINB,SDAP; if SDA is high

sec  ; set carry flag

rcall i2c_hp_delay; half period delay

ret





;***************************************************************************

;*

;* FUNCTION

;* i2c_do_transfer

;*

;* DESCRIPTION

;* Executes a transfer on bus. This is only a combination of i2c_read

;* and i2c_write for convenience.

;*

;* USAGE

;* i2cadr - Must have the same direction as when i2c_start was called.

;* see i2c_read and i2c_write for more information.

;*

;* RETURN

;* (depends on type of transfer, read or write)

;*

;* NOTE

;* IMPORTANT! : This funtion must be directly followed by i2c_read.

;*

;***************************************************************************



i2c_do_transfer:

sbrs i2cadr,b_dir; if dir = write

rjmp i2c_write; goto write data





;***************************************************************************

;*

;* FUNCTION

;* i2c_read

;*

;* DESCRIPTION

;* Reads data (one byte) from the I2C bus.

;*

;* USAGE

;* Carry flag -  If set no acknowledge is given to the slave

;*   indicating last read operation before a STOP.

;*   If cleared acknowledge is given to the slave

;*   indicating more data.

;*

;* RETURN

;* i2cdata - Contains received data.

;*

;* NOTE

;* IMPORTANT! : This funtion must be directly followed by i2c_put_ack.

;*

;***************************************************************************



i2c_read:

rol i2cstat  ; store acknowledge

   ; (used by i2c_put_ack)

ldi i2cdata,0x01; data = 0x01

i2c_read_bit:  ; do

sbi DDRB,SCLP;  force SCL low

rcall i2c_hp_delay; half period delay



cbi DDRB,SCLP; release SCL

rcall i2c_hp_delay; half period delay



clc  ; clear carry flag

sbic PINB,SDAP; if SDA is high

sec  ;  set carry flag



rol i2cdata  ;  store data bit

brcc i2c_read_bit; while receive register not full





;***************************************************************************

;*

;* FUNCTION

;* i2c_put_ack

;*

;* DESCRIPTION

;* Put acknowledge.

;*

;* USAGE

;* (used only by i2c_read in this version)

;*

;* RETURN

;* none

;*

;***************************************************************************



i2c_put_ack:

sbi DDRB,SCLP; force SCL low



ror i2cstat  ; get status bit

brcc i2c_put_ack_low; if bit low goto assert low

cbi DDRB,SDAP; release SDA

rjmp i2c_put_ack_high

i2c_put_ack_low:  ; else

sbi DDRB,SDAP; force SDA low

i2c_put_ack_high:



rcall i2c_hp_delay; half period delay

cbi DDRB,SCLP; release SCL

i2c_put_ack_wait:

sbis PINB,SCLP; wait SCL high

rjmp i2c_put_ack_wait

rcall i2c_hp_delay; half period delay

ret





;***************************************************************************

;*

;* FUNCTION

;* i2c_stop

;*

;* DESCRIPTION

;* Assert stop condition.

;*

;* USAGE

;* No parameters.

;*

;* RETURN

;* None.

;*

;***************************************************************************



i2c_stop:

sbi DDRB,SCLP; force SCL low

sbi DDRB,SDAP; force SDA low

rcall i2c_hp_delay; half period delay

cbi DDRB,SCLP; release SCL

rcall i2c_qp_delay; quarter period delay

cbi DDRB,SDAP; release SDA

rcall i2c_hp_delay; half period delay

ret





;***************************************************************************

;*

;* FUNCTION

;* i2c_init

;*

;* DESCRIPTION

;* Initialization of the I2C bus interface.

;*

;* USAGE

;* Call this function once to initialize the I2C bus. No parameters

;* are required.

;*

;* RETURN

;* None

;*

;* NOTE

;* PORTD and DDRD pins not used by the I2C bus interface will be

;* set to Hi-Z (!).

;*

;* COMMENT

;* This function can be combined with other PORTD initializations.

;*

;***************************************************************************

;

;i2c_init:

; clr i2cstat  ; clear I2C status register (used

;    ; as a temporary register)

; out PORTB,i2cstat; set I2C pins to open colector

; out DDRB,i2cstat

; ret











;---------------

;Interrupts routine just send a signal to a thread. If you need a VERY short interrupt

;response you can put some instructions here, then send the signal to the thread

;---------------

TIMERDRV:

 in SaveStatus,SREG



 ldi Main1, 256-3

 out TCNT0, Main1

 sbr MiscFlags, EXP2(Thread3Signal);wakeup thread 3



 out SREG,SaveStatus

 reti





;---------------

INT0DRV:

 in SaveStatus,SREG

 sbr MiscFlags, EXP2(Thread2Signal);wakeup thread 2

 out SREG,SaveStatus

 reti





;-----------------

;This is the scheduler, the core of the nanoKernel. You can decide to go sleep

; when there's nothing to do. You can also put there the watchdog reset instruction.

;-----------------

SCHEDULER:

 sei    ;be sure interrupts on here



;if you don't want to go sleep remove next 3 instr

 tst MiscFlags

 brne SCHEDULER1

 sleep

SCHEDULER1:

 sbrc MiscFlags, Thread1Status;test if thread1 is ready

 rjmp SCHEDRDY1

;check for wakeup

 sbrs MiscFlags, Thread1Signal;test if thread1 received a signal

 rjmp SCHEDULER2

 cbr MiscFlags, EXP2(Thread1Signal);clear signal

SCHEDRDY1:

;switch to thread 1

 sbr MiscFlags, EXP2(Thread1Status)

 out SREG,SaveThr1Status

 rjmp THR1WAKEUP



SCHEDULER2:

 sbrc MiscFlags, Thread2Status;test if thread2 is ready

 rjmp SCHEDRDY2

;check for wakeup

 sbrs MiscFlags, Thread2Signal;test if thread1 received a signal

 rjmp SCHEDULER3

 cbr MiscFlags, EXP2(Thread2Signal);clear signal

SCHEDRDY2:

;switch to thread 2

 sbr MiscFlags, EXP2(Thread2Status)

 out SREG,SaveThr2Status

 rjmp THR2WAKEUP

SCHEDULER3:

 sbrc MiscFlags, Thread3Status;test if thread3 is ready

 rjmp SCHEDRDY3

;check for wakeup

 sbrs MiscFlags, Thread3Signal;test if thread1 received a signal

 rjmp SCHEDULER

 cbr MiscFlags, EXP2(Thread3Signal);clear signal

SCHEDRDY3:

;switch to thread 3

 sbr MiscFlags, EXP2(Thread3Status)

 out SREG,SaveThr3Status

 rjmp THR3WAKEUP






Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.