Hi Alaric,

On 06/19/2012 10:25 PM, Alaric Snell-Pym wrote:
>>> I plan to customise it a bit (I've written up a bunch of portpin:
>>> >>  declarations that match the arduino pin names, and I'm working on
>>> >>  adapting the demonstration PWM and ADC code from lib/ into something
>>> >>  that,
>> >
>> >  Erich has written a lot of code for the danger shield. Maybe you
>> >  two could collaborate?
> Sounds good to me!
> 

I have used the code below to run a simple test script on newly assembled
danger shields. Missing parts and/or known "bad" code"
a. not properly debouncing the switches
b. the menu logic
c. I have not bothered to properly convert the temperature sensor readings
   into Celsius or so. Please note that the connection details of this sensor
   have changed between board revisions!


Have the appropriate amount of fun.
Erich

-----------------------------------------------------------------------------------
\ 2011-03-06  EW
\ test arduino duemilanove + danger shield rev. 14
\ 2012-02-15  EW  changed for dangershield rev. 16

\ hw layout
\ arduino | atmega328p                | danger shield
\      D0 |        PD0   rx           | 
\      D1 |        PD1   tx           |
\      D2 |        PD2   int0         |
\      D3 |        PD3   int1  oc2b   |   bz      (buzzer)
\      D4 |        PD4   t0           |   sr_in   (shift register DS)
\      D5 |        PD5   t1    oc0b   |   led1
\      D6 |        PD6         oc0a   |   led2
\      D7 |        PD7                |   sr_latch (shift register /OE)
\                                     |
\      D8 |        PB0    icp         |   sr_clk  (shift register SH_CP)
\      D9 |        PB1         oc1a   |
\     D10 |        PB2    /ss  oc1b   |   sw1     (switch)
\     D11 |        PB3    mosi oc2a   |   sw2     (switch)
\     D12 |        PB4    miso        |   sw3     (switch)
\     D13 |        PB5    sck         |
\                                     |
\      A0 |        PC0    adc0        |   sl3     (slider)
\      A1 |        PC1    adc1        |   sl2     (slider)
\      A2 |        PC2    adc2        |   sl1     (slider)
\      A3 |        PC3    adc3        |   light   (photo cell)
\      A4 |        PC4    adc4  scl   |   temp    (temperature)
\      A5 |        PC5    adc5  sda   |

\ make marker

marker --start--

decimal

PORTB 2 portpin: sw1
PORTB 3 portpin: sw2
PORTB 4 portpin: sw3

PORTD 5 portpin: led1
PORTD 6 portpin: led2

PORTD 3 portpin: bz

PORTC 2 portpin: sl1
PORTC 1 portpin: sl2
PORTC 0 portpin: sl3

PORTC 3 portpin: photocell
PORTC 4 portpin: thermometer

PORTD 4 portpin: sr_in
PORTD 7 portpin: sr_oe \ output enable
PORTB 0 portpin: sr_cl

variable 1delay  20 1delay !
: msg_quit
  ." press switch 1 (D10) to quit" cr
;


\ --- switches -----------------------------------------------
: sw1? ( -- true|false )
  sw1 pin_low? if       \ if switch1 pressed
    &20 ms              \ { wait a little
    sw1 pin_low? if     \   if switch1 still pressed
      -1                \   { "true" on stack
    else                \   }else
      0                 \   { "false on stack
    then                \   }
  else                  \ }else
    0                   \ { "false" on stack
  then                  \ }
;

\ --- buzzer -------------------------------------------------

\ 2 ms T_period =^= 500 Hz
: buzz ( cycles -- )
  0 ?do bz low 1ms bz high 1ms loop
;

\ --- analog digital converter -------------------------------
\ --- adc ---

: or!   dup c@ rot or swap c! ;

\ pin>pos
\     convert bitmask of portpin: back to value (bitposition)
: pin>pos       ( pinmask portaddr -- pos )
  drop          ( -- pinmask )
  log2          ( -- pos_of_most_significant_bit )
;

: adc.init ( -- )
  \ ADMUX
  \ A_ref is NOT connected externally
  \ ==> need to set bit REFS0 in register ADMUX
  [ 1 5 lshift      \ ADLAR
    1 6 lshift or   \ REFS0
  ] literal ADMUX c!
  \ ADCSRA
  [ 1 7 lshift      \ ADEN   ADC enabled
    1 2 lshift or   \ ADPS2  prescaler = 128
    1 1 lshift or   \ ADPS1  .
    1          or   \ ADPS0  .
  ] literal ADCSRA c!
;
: adc.init.pin ( bitmask portaddr -- )
  over over high
  pin_input
;
  
1 6 lshift constant ADSC_MSK \ ADStartConversion bitmask
: adc.start
  \ start conversion
  ADSC_MSK ADCSRA or!
;
: adc.wait
  \ wait for completion of conversion
  begin
    ADCSRA c@ ADSC_MSK and 0=
  until
;
: adc.channel! ( channel -- )
  7 and                 \ clip channel to 0..7
  ADMUX c@ 7 invert and \ read ADMUX, clear old channel
  or                    \ add new channel
  ADMUX c!              \ write
;
: adc.get10 ( channel -- a )
  adc.channel! adc.start adc.wait
\ 10 bit
  ADCL c@
  ADCH c@ 8 lshift + 6 rshift
;
: adc.get ( channel -- a )
  adc.channel! adc.start adc.wait
\ 8 bit
  ADCH c@
;

\ --- shift register -----------------------------------------

: bit>sr ( bit -- )
  if sr_in high else sr_in low then
  sr_cl high noop sr_cl low noop
;

: get.bit ( byte pos -- bit )
  1 swap lshift    \ -- byte bitmask
  and              \ -- bit
;

\ clock one byte out, MSB first!
: byte>sr ( byte -- )
  8 0 do
    dup 7 i -  \ 7 6 5 ... 0: MSB first!
    get.bit
    bit>sr
  loop
  drop
;

: >7seg
  invert
  byte>sr
  sr_oe low noop sr_oe high
;


create HexDigits
$3f ,  \ 0
$06 ,  \ 1
$5b ,  \ 2
$4f ,  \ 3
$66 ,  \ 4
$6d ,  \ 5
$7d ,  \ 6
$07 ,  \ 7
$7f ,  \ 8
$6f ,  \ 9
$77 ,  \ A
$7c ,  \ b
$58 ,  \ c
$5e ,  \ d
$79 ,  \ E
$71 ,  \ F

$80 constant dec.point
: emit.7seg ( n -- )
  dup 0 $F within if
    HexDigits + @i >7seg
  else
    drop
  then
;

\ --- convert thermometer reading --------------------------


: .T
  thermometer pin>pos adc.get10  . cr
;


\ --- test functions ---------------------------------------
: test_switches
  ." press switch 2,3 to light up led 1,2" cr
  msg_quit

  begin
    sw2 pin_low? if led1 high else led1 low then
    sw3 pin_low? if led2 high else led2 low then
  sw1? until
;

: test_buzzer
  ." press switch 2 (D11) to test buzzer" cr
  msg_quit
  begin
    sw2 pin_low? if 500 buzz then
  sw1? until
;

: test_sliders
  ." move sliders" cr
  msg_quit
  begin
    sl1 pin>pos adc.get 4 u0.r space space
    sl2 pin>pos adc.get 4 u0.r space space
    sl3 pin>pos adc.get 4 u0.r    $0d emit
    1delay @ ms
  sw1? until
  cr
;

: test_photocell
  ." light/shadow photocell" cr
  msg_quit
  begin
    photocell pin>pos adc.get 4 u0.r    $0d emit
    1delay @ ms
  sw1? until
  cr
;

: test_thermometer
  ." warm/cool thermometer" cr
  msg_quit
  begin
    thermometer pin>pos adc.get10 4 u0.r    $0d emit
    1delay @ ms
  sw1? until
  cr
;


: test_bits.7seg
  8 0 do
    1 i lshift >7seg
    500 ms
  loop
;
: test_emit.7seg
  $10 0 do
    i emit.7seg
    500 ms
  loop
;
: test_7seg
  ." show single segments on 7seg" cr
  test_bits.7seg
  1000 ms
  ." show hex numbers on 7seg" cr
  test_emit.7seg
  1000 ms
;

\ --- main: init, run --------------------------------------
: init
  led1 pin_output
  led2 pin_output
  bz   pin_output

  \ set pins to high (internal pullup)
  sw1 high sw1 pin_input
  sw2 high sw2 pin_input
  sw3 high sw3 pin_input
  
  adc.init
  sl1 adc.init.pin
  sl2 adc.init.pin
  sl3 adc.init.pin
  photocell adc.init.pin
  thermometer adc.init.pin

  sr_in high sr_in pin_output
  sr_oe high sr_oe pin_output
  sr_cl low  sr_cl pin_output
  $ff >7seg
;


\ --- pwm: timer/counter0, led1,2 ---
\ D5 | PD5  t1  oc0b | led1
\ D6 | PD6      oc0a | led2
\ timer/counter0
\ fast pwm mode
\ TCCR0A bits
\ .  COM0A[1,0] = 1,0    (non inverted mode)
\ .  COM0B[1,0] = 1,0    (non inverted mode)
\ .  WGM0[1,0]  = 1,1    (mode3: fast pwm)
\ TCCR0B bits
\ .  CS[2,1,0]  = 0,1,1  (clk_io/64)

\ TIMSK0 TIFR0 TCNT0 TCCR0B TCCR0A OCR0B OCR0A

: pwm.leds.init
  0 TCNT0 c! \ clear counter
  led1 high led1 pin_output
  led2 high led2 pin_output
  \ TCCR0A = COM0A1 | COM0B1 | WGM01 | WGM00
  %10100011 TCCR0A c!
  \ TCCR0B = CS1 | CS0
  %00000011 TCCR0B c!
;
\ control brightness via registers
\ OCR0A  (D6)
\ OCR0B  (D5)

: pwm.leds.off
  led1 low led2 low
  0 TCCR0A c!
  0 TCCR0B c!
  0 OCR0A  c!
  0 OCR0B  c!
  0 TCNT0  c!
;

: test_leds_pwm_slider
  ." move sliders to control leds (pwm)" cr
  msg_quit
  pwm.leds.init
  begin
    sl1 pin>pos adc.get 5 -  0 max  OCR0B c!
    sl2 pin>pos adc.get 5 -  0 max  OCR0A c!
    1ms
  sw1? until
  pwm.leds.off
  cr
;


\ --- pwm: timer/counter2, buzzer ---
\ D3 | PD3 int1 oc2b | bz

\ timer/counter2
\ clear timer on compare match, ctc mode
\ TCCR2A bits
\ .  COM2B[1,0] = 0,1    (non inverted mode)
\ .  WGM2[1,0]  = 1,0    (mode2: ctc)
\ TCCR2B bits
\ .  CS[2,1,0]  = 1,1,1  (clk_t2s/256)

\ TIMSK0 TIFR0 TCNT0 TCCR0B TCCR0A OCR0B OCR0A

: pwm.bz.init
  0 TCNT2 c! \ clear counter
  bz high bz pin_output

  \ TCCR2A =  COM0B0 | WGM01 
  %00010010 TCCR2A c!
  \ TCCR2B = CS1 | CS0
  %00000110 TCCR2B c!
;
\ control frequency via register
\ OCR2A
: pwm.bz.off
  0 TCNT2  c!
  0 TCCR2A c!
  0 TCCR2B c!
  0 OCR2A  c!
  0 OCR2B  c!
;
: buzzer_pwm_once
  pwm.bz.init
  $20 OCR2A c!  200 ms
  $30 OCR2A c!  200 ms
  $40 OCR2A c!  200 ms
  $0  OCR2A c!  200 ms
;
: test_buzzer_pwm
  ." press switch 2 (D11) to test buzzer (pwm)" cr
  msg_quit
  begin
    sw2 pin_low? if 500 buzzer_pwm_once then
  sw1? until
  pwm.bz.off
;

: test_bz_pwm_slider
  ." move slider1 to control buzzer (pwm)" cr
  msg_quit
  pwm.bz.init
  begin
    sl1 pin>pos adc.get 5 -  0 max  OCR2A c!
    1ms
  sw1? until
  pwm.bz.off
  cr
;


\ --- --- ---

variable state
9 constant max_state

: run

  init
  0 state !
  20 1delay !

  ." press switch 1 (D10) for next test" cr
  begin

    sw1? if
      state @ 1+
      dup max_state > if drop 0 then 
      dup state !
      . cr
    then

\   state @ 0 =   ( do nothing )

    state @ 1 = if test_switches    then
    state @ 2 = if test_buzzer      then
    state @ 3 = if test_buzzer_pwm  then
    state @ 4 = if test_sliders     then
    state @ 5 = if test_leds_pwm_slider then
    state @ 6 = if test_photocell   then
    state @ 7 = if test_thermometer then
    state @ 8 = if test_7seg  1 state +! then

    \ wait some
    1delay @ 5 * ms

  key? until
  key drop
;

\ fin

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
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