Hello,

I'm currently working on a sensor which must be powered on battery.
Measurements show that the idle atmega-32 sinks some 24 mA when
idle. When going to "powersave" mode, energy consumption drops to
1 mA. In this mode timer2 (connected to a clock crystal) will continue
to run. On timer2 overflow, the controller wakes up and continues
the program. First, the timer2 interrupt service routine is run, which
will increment ticks by 1. Then the main loop "run" will continue.
If the counter "ticks" is above some threshold "idle.ticks", the
scheduled job is called. Then the controller is sent back to sleep.
Ticks are 8 seconds in the example below.

Please find 2 files below:

1. sleep-m32.asm
The bits controlling sleep mode are in a different register and position
than in the atmega328p, from which the code in the repository is derived.
I have not made any attempt to solve the problem at hand in a
general way. Add this file instead in dict_appl_core.inc.

2. run_powersave.fs
A working example which will light up LEDs connected to +5V and PORTB
for 1 second, then go to sleep for 4 ticks (32 seconds). For timer2
a clock crystal must be connected.


Enjoy,
Erich

\ -----------------------------------------------------------------
; sleep-m32.asm
;  sleep   ( mode -- )
;
\ ---<snip>---

; 2012-01-15  ew
; on atmega-32 sleep modes are handled via a different register
; MCUCR, not SMCR and bits at different bit location
; 6-4, not 3-1.
; SE is bit 7 not 0

; ( mode -- )
; MCU
; put the controller into the specified sleep mode
VE_SLEEP:
        .dw $ff05
        .db "sleep", 0
        .dw VE_HEAD
        .set VE_HEAD = VE_SLEEP
XT_SLEEP:
        .dw PFA_SLEEP
PFA_SLEEP:
        andi    tosl, 7                         ; leave only legal mode bits
        swap    tosl                            ; move to correct location 
(bits 6-4, atmega32)
        ori     tosl, $80                       ; set the SE bit (atmega32: bit 
7, not bit 0)
        out     MCUCR, tosl                     ; set the sleep config 
(atmega32: MCUCR not SMCR)
        sleep                                   ; nighty-night
        ;; atmega32: the 4 lower bits of MCUCR should not be touched
        in      tosl, MCUCR
        andi    tosl, $0F
        out     MCUCR, tosl
        ;clr    tosl                            ; need to clean up the SMCR reg 
before we leave
        ;out    SMCR, tosl                      ; 0 protects against accidental 
sleeps
        loadtos                                 ; pop argument from stack
     jmp        DO_NEXT

\ -----------------------------------------------------------------
\ 2012-01-26  ew  run_powersafe.fs
\ tested on atmega-32, amforth-4.6

\ timer2 on clock crystal, overflow after 8 secs
\ timer2-isr: increment counter ticks


\ stolen from devices/atmega32/atmega32.frt
$38 constant PORTB       \ Port B Data Register
$37 constant DDRB        \ Port B Data Direction Register
$45 constant TCCR2       \ Timer/Counter2 Control Register
$59 constant TIMSK       \ Timer/Counter Interrupt Mask Register
$42 constant ASSR        \ Asynchronous Status Register
$45 constant TCCR2       \ Timer/Counter2 Control Register
$58 constant TIFR        \ Timer/Counter Interrupt Flag register
$0A constant TIMER2_OVFAddr \ Timer/Counter2 Overflow


variable ticks
\ overflow2 interupt service routine: increment ticks
: tick_isr_slow
   1 ticks +!
;
\ enable ticks
\ crystal:   32768 /sec
\ clock src: 32768/1024 /sec = 32 /sec
\ overflow:     32/256  /sec = 1/8 /sec: T=8 sec
: +ticks-slow
   $7 TCCR2 c!                           \ 111 = clock_ts2/1024
   $8 ASSR  c!                           \ source: 32 kiHz crystal
   ['] tick_isr_slow TIMER2_OVFAddr int! \ register interupt
   TIMSK c@ $40 or TIMSK c!               \ enable timer2 interupt
;
\ disable ticks
: -ticks
   TIMSK c@
   [ $40 invert $ff and ] literal
   and TIMSK c! \ clr Timer 2
   $00 ASSR  c!
   $00 TCCR2 c!
   $C0 TIFR  c! \ clear interrupt flags, jibc
;


4 constant idle.ticks   \ 4 * 8 = 32 seconds wait
: init
   idle.ticks 1+ ticks ! \ run job once on startup
   +ticks-slow

   $ff DDRB c!           \ make PORTB output
   $ff PORTB c!
;

\ job does one round of work, whatever it is
: ms  0 ?do 1ms loop ;
: job
   $00 PORTB c!
   &1000 ms
   $ff PORTB c!
;

: run
   init
   begin
     ticks @  idle.ticks  > if
       job
       1 ticks !         \ reset ticks counter
     then
     $03 sleep           \ goto sleep here
   again
;

: run-turnkey
   applturnkey
   run
;

\ ' run-turnkey is turnkey
\ fin
\ -----------------------------------------------------------------
\ -----------------------------------------------------------------

------------------------------------------------------------------------------
Try before you buy = See our experts in action!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-dev2
_______________________________________________
Amforth-devel mailing list for http://amforth.sf.net/
Amforth-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/amforth-devel

Reply via email to