atom-msp430 (empty) → 0.5.0
raw patch · 9 files changed
+271/−0 lines, 9 filesdep +atomdep +basedep +mtlsetup-changed
Dependencies added: atom, base, mtl
Files
- LICENSE +20/−0
- Language/Atom/MSP430.hs +16/−0
- Language/Atom/MSP430/Compile.hs +133/−0
- Language/Atom/MSP430/DigitalIO.hs +24/−0
- Language/Atom/MSP430/Interrupts.hs +6/−0
- Language/Atom/MSP430/TimerA.hs +25/−0
- Language/Atom/MSP430/Watchdog.hs +21/−0
- Setup.hs +2/−0
- atom-msp430.cabal +24/−0
+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2013 Daniel Buckmaster + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +
+ Language/Atom/MSP430.hs view
@@ -0,0 +1,16 @@+module Language.Atom.MSP430 ( + module Language.Atom, + module Language.Atom.MSP430.Watchdog, + module Language.Atom.MSP430.DigitalIO, + module Language.Atom.MSP430.TimerA, + module Language.Atom.MSP430.Interrupts, + module Language.Atom.MSP430.Compile + ) where + +import Language.Atom +import Language.Atom.MSP430.Watchdog +import Language.Atom.MSP430.DigitalIO +import Language.Atom.MSP430.TimerA +import Language.Atom.MSP430.Interrupts +import Language.Atom.MSP430.Compile +
+ Language/Atom/MSP430/Compile.hs view
@@ -0,0 +1,133 @@+module Language.Atom.MSP430.Compile ( + MSP430Compilation (..), + mspProgram, wiringProgram, simpleProgram, energiaProgram, + mspCompile + ) where + +import Language.Atom +import Control.Monad +import System.IO + +-- | Program information. It specifies the functions that should be used in specific +-- roles in the compiled code, as well as other configuration information. +data MSP430Compilation = MSP430Compilation { + setupFn :: Maybe (Atom ()), -- ^ Function called once when the MCU starts up. + setupFnName :: String, -- ^ Name of the setup function in the generated code. + loopFn :: Maybe (Atom ()), -- ^ Function called in a busy loop after setup. + loopFnName :: String, -- ^ Name of the loop function in the generated code. + timerAISR :: Maybe (Atom ()), -- ^ Function to run when a TimerA CCR interrupt happens. + timerAISRName :: String, -- ^ Name of the TimerA interrupt function in the generated code. + watchdogISR :: Maybe (Atom ()), -- ^ Function to call when the WDT interrupts. + watchdogISRName :: String, -- ^ Name of the WDT interrupt function in the generated code. + port1ISR :: Maybe (Atom ()), -- ^ Function to call when there is a PORT1 interrupt. + port1ISRName :: String, -- ^ Name of the PORT1 interrupt function. + port2ISR :: Maybe (Atom ()), -- ^ Function to call when there is a PORT2 interrupt. + port2ISRName :: String, -- ^ Name of the PORT2 interrupt function. + mainFile :: String, -- ^ Name of the main file to generate. + emitMainFn :: Bool -- ^ Add a main function calling setup and loop? + } + +-- | Default program to construct your own programs from. Contains Nothing and generates a +-- basic main.c. Use it by overriding the functions it generates, and optionally their names. +mspProgram = MSP430Compilation { + setupFn = Nothing, + setupFnName = "setup", + loopFn = Nothing, + loopFnName = "loop", + timerAISR = Nothing, + timerAISRName = "timerAISR", + watchdogISR = Nothing, + watchdogISRName = "wdtISR", + port1ISR = Nothing, + port1ISRName = "p1ISR", + port2ISR = Nothing, + port2ISRName = "p2ISR", + mainFile = "main.c", + emitMainFn = True + } + +-- | Easy settings for a Wiring-style program with setup and loop functions. Expects a device extension +-- for header files - i.e. running with "g2231" wihh generate files that #include "msp430g2231.h" +wiringProgram s l = mspProgram { + setupFn = Just s, + loopFn = Just l + } + +-- | Easy settings for a program with just a setup function. +simpleProgram s = mspProgram { + setupFn = Just s + } + +-- | Easy settings for a program with setup and loop, but no main function. +energiaProgram s l = mspProgram { + setupFn = Just s, + loopFn = Just l, + emitMainFn = False + } + +-- | Compile a program given by the compilation specification. Compiles all functions into library files +-- and then generates a main file which calls these functions in the appropriate way. +mspCompile :: String -> MSP430Compilation -> IO () +mspCompile h c = do + let headers = unlines $ map (\h -> "#include \"msp430" ++ h ++ ".h\"") [h] + let compile' = maybeCompile defaults { + cRuleCoverage = False, + cAssert = False, + cCode = \_ _ _ -> (headers, "") + } + compile' (setupFnName c) (setupFn c) + compile' (loopFnName c) (loopFn c) + compile' (timerAISRName c) (timerAISR c) + compile' (watchdogISRName c) (watchdogISR c) + compile' (port1ISRName c) (port1ISR c) + compile' (port2ISRName c) (port2ISR c) + putStrLn $ "Generating " ++ mainFile c ++ "..." + hFlush stdout + withFile (mainFile c) WriteMode $ \h -> do + let put = hPutStrLn h + let header' = maybeHeader h + let interrupt' = maybeInterrupt h + header' (setupFnName c) (setupFn c) + header' (loopFnName c) (loopFn c) + header' (timerAISRName c) (timerAISR c) + header' (watchdogISRName c) (watchdogISR c) + header' (port1ISRName c) (port1ISR c) + header' (port2ISRName c) (port2ISR c) + when (emitMainFn c) $ do + put headers + put "\nint main(void) {" + case setupFn c of + Just f -> put $ " " ++ setupFnName c ++ "();" + Nothing -> return () + case loopFn c of + Just f -> put $ " while(1) " ++ loopFnName c ++ "();" + Nothing -> return () + put " return 0;" + put "}\n" + interrupt' (watchdogISR c) (watchdogISRName c) "WDT_VECTOR" + interrupt' (timerAISR c) (timerAISRName c) "TIMERA0_VECTOR" + interrupt' (port1ISR c) (port1ISRName c) "PORT1_VECTOR" + interrupt' (port2ISR c) (port2ISRName c) "PORT2_VECTOR" + return () + +maybeCompile s n f = case f of + Nothing -> return () + Just fn -> do + putStrLn $ "Compiling " ++ n ++ "..." + hFlush stdout + compile n s fn + return () + +maybeHeader h header f = case f of + Just _ -> hPutStrLn h $ "#include \"" ++ header ++ ".h\"" + Nothing -> return () + +maybeInterrupt h a n v = case a of + Just _ -> do + let put = hPutStrLn h + put $ "#pragma vector=" ++ v + put $ "__interrupt void __" ++ n ++ "(void) {" + put $ " " ++ n ++ "();" + put "}\n" + Nothing -> return () +
+ Language/Atom/MSP430/DigitalIO.hs view
@@ -0,0 +1,24 @@+module Language.Atom.MSP430.DigitalIO where + +import Language.Atom + +port1In = word8' "P1IN" -- ^ Read the value of PORT1 pins when used in input mode. +port1Out = word8' "P1OUT" -- ^ Set the values of PORT1 pins when used in output mode. +port1Dir = word8' "P1DIR" -- ^ Choose the input/output modes of PORT1 pins (1 = output). +port1Resistors = word8' "P1REN" -- ^ Enable pullup/pulldown resistors of PORT1 pins. +port1Function = word8' "P1SEL" -- ^ + +port1InterruptEnable = word8' "P1IE" -- ^ Enable interrupts for PORT1 pins in input mode. +port1InterruptFlags = word8' "P1IFG" -- ^ Interrupt flags for PORT1 pins. A flag is set when an interrupt occurs; you should clear it manually. +port1InterruptEdgeSelect = word8' "P1IES" -- ^ Interrupt edge select: if set to 1, the pin responds to a falling edge. + +port2In = word8' "P2IN" -- ^ Read the value of PORT2 pins when used in input mode. +port2Out = word8' "P2OUT" -- ^ Set the values of PORT2 pins when used in output mode. +port2Dir = word8' "P2DIR" -- ^ Choose the input/output modes of PORT2 pins (2 = output). +port2Resistors = word8' "P2REN" -- ^ Enable pullup/pulldown resistors of PORT2 pins. +port2Function = word8' "P2SEL" -- ^ + +port2InterruptEnable = word8' "P2IE" -- ^ Enable interrupts for PORT2 pins in input mode. +port2InterruptFlags = word8' "P2IFG" -- ^ Interrupt flags for PORT2 pins. A flag is set when an interrupt occurs; you should clear it manually. +port2InterruptEdgeSelect = word8' "P2IES" -- ^ Interrupt edge select: if set to 2, the pin responds to a falling edge. +
+ Language/Atom/MSP430/Interrupts.hs view
@@ -0,0 +1,6 @@+module Language.Atom.MSP430.Interrupts where + +import Language.Atom + +interruptEnable = word8' "IE1" -- ^ Global interrupt vector. +interruptFlags = word8' "IFG1" -- ^ Global interrupt flags.
+ Language/Atom/MSP430/TimerA.hs view
@@ -0,0 +1,25 @@+module Language.Atom.MSP430.TimerA where + +import Language.Atom +import Data.Word + +taSource = 0x0000 :: Word16 -- ^ Source Timer A from TACLK. +taSourceACLK = 0x0100 :: Word16 -- ^ Source Timer A from ACLK. +taSourceSMCLK = 0x0200 :: Word16 -- ^ Source Timer A from SMCLK. +taSourceINCLK = 0x0300 :: Word16 -- ^ Source Timer A from INCLK. +taClear = 0x0004 :: Word16 -- ^ Clear Timer A (reset it to 0). +taInterruptEnabled = 0x0002 :: Word16 -- ^ Enable the Timer A interrupt. +taStopMode = 0x0000 :: Word16 -- ^ Stop the timer from counting. +taUpMode = 0x0010 :: Word16 -- ^ Timer counts from 0 to TACCR0. +taContinuousMode = 0x0020 :: Word16 -- ^ Timer counts from 0 to 0xFFFF. +taUpDownMode = 0x0030 :: Word16 -- ^ Timer counts from 0 to TACCR0 to 0. +taSourceDiv1 = 0x0000 :: Word16 -- ^ Divide timer input source by 1. +taSourceDiv2 = 0x0040 :: Word16 -- ^ Divide timer input source by 2. +taSourceDiv4 = 0x0080 :: Word16 -- ^ Divide timer input source by 4. +taSourceDiv8 = 0x00C0 :: Word16 -- ^ Divide timer input source by 8. + +taCCRInterrupt = 0x0010 :: Word16 -- ^ Interrupt on a Timer A CCR. + +timerAControl = word16' "TACTL" -- ^ Timer A control register. +timerACCR0 = word16' "TACCR0" -- ^ Timer A capture/compare register 0. +timerACCC0 = word16' "TACCTL0" -- ^ Timer A capture/compare control register 0.
+ Language/Atom/MSP430/Watchdog.hs view
@@ -0,0 +1,21 @@+module Language.Atom.MSP430.Watchdog where + +import Language.Atom +import Data.Word + +wdtPassword = 0x5A00 :: Word16 -- ^ Password bits to change the waychdog settings. Include this in every write to 'watchdog'. +wdtHold = 0x0080 :: Word16 -- ^ Stop the watchdog timer. +wdtNMIFalling = 0x0040 :: Word16 -- ^ NMI interrupt on falling edge. +wdtNMI = 0x0020 :: Word16 -- ^ NMI interrupt. +wdtIntervalMode = 0x0010 :: Word16 -- ^ Use the timer as an interval counter with interrupt. +wdtClearCounter = 0x0008 :: Word16 -- ^ Clear the WDT counter when in interval mode. +wdtUseAuxClock = 0x0004 :: Word16 -- ^ Source WDT from ACLK. +wdtSourceDiv15 = 0x0000 :: Word16 -- ^ Divide the timer input by 2^15. +wdtSourceDiv13 = 0x0001 :: Word16 -- ^ Divide the timer input by 2^13. +wdtSourceDiv9 = 0x0002 :: Word16 -- ^ Divide the timer input by 2^9. +wdtSourceDiv6 = 0x0003 :: Word16 -- ^ Divide the timer input by 2^6. + +wdtInterruptEnable = 0x01 :: Word8 -- ^ Enable the WDT interrupt in 'interruptEnable'. +wdtNMIInterruptEnable = 0x10 :: Word8 -- ^ Enable the WDT's NMI interrupt in 'interruptEnable'. + +watchdog = word16' "WDTCTL" -- ^ Watchdog control register.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple +main = defaultMain
+ atom-msp430.cabal view
@@ -0,0 +1,24 @@+name: atom-msp430 +version: 0.5.0 +synopsis: Convenience functions for using Atom with the MSP430 microcontroller family. +-- description: +homepage: https://github.com/eightyeight/atom-msp430 +license: MIT +license-file: LICENSE +author: Daniel Buckmaster +maintainer: dan.buckmaster@gmail.com +-- copyright: +category: Embedded +build-type: Simple +cabal-version: >=1.8 + +library + exposed-modules: Language.Atom.MSP430, + Language.Atom.MSP430.Watchdog, + Language.Atom.MSP430.DigitalIO, + Language.Atom.MSP430.TimerA, + Language.Atom.MSP430.Interrupts, + Language.Atom.MSP430.Compile + build-depends: base ==4.5.*, + mtl, + atom >= 1.0.12