Skip to content

Commit

Permalink
Merge pull request todbot#199 from gregnwosu/master
Browse files Browse the repository at this point in the history
haskell foreign function bindings for blink1 device
  • Loading branch information
todbot committed Jan 10, 2015
2 parents 15ee8ca + 8bf9779 commit ab32cdf
Show file tree
Hide file tree
Showing 7 changed files with 217 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -181,3 +181,9 @@ pip-log.txt
*.def
*.dll
*.exp
/commandline/blink1-tool
/haskell/.cabal-sandbox/**/*
/commandline/blink1-lib-v1.95-linux-armv7l.zip
/commandline/blink1-tool-v1.95-linux-armv7l.zip
/haskell/Main
/haskell/Main.hi
43 changes: 43 additions & 0 deletions haskell/Blink1Tool.hsc
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{-# LANGUAGE CPP, ForeignFunctionInterface, EmptyDataDecls #-}

module Blink1Tool where

#include <blink1-lib.h>
import Foreign
import Foreign.C.Types
import Foreign.C.String
import System.IO.Unsafe
import Control.Exception
import qualified Data.ByteString.Char8 as B
import GHC.Float

foreign import ccall unsafe "blink1-lib.h blink1_open"
c_blink1open :: IO (Ptr Blink1Device)

foreign import ccall unsafe "blink1-lib.h blink1_enumerate"
c_blink1_enumerate :: IO (CInt)

foreign import ccall unsafe "blink1-lib.h blink1_close"
c_blink1_close:: Ptr Blink1Device -> IO ()

foreign import ccall "blink1-lib.h blink1_fadeToRGBN"
c_blink1_fadeToRGBN :: Ptr Blink1Device -> CUShort -> CUChar -> CUChar -> CUChar -> CUChar -> IO CInt

data Blink1Device

data Blink1Tool = Blink1Tool !(ForeignPtr Blink1Device)
deriving (Eq, Ord, Show)

blink1device :: IO (Either String (ForeignPtr Blink1Device))
blink1device = do
blink1device_ptr <- c_blink1open
if blink1device_ptr == nullPtr
then do
return (Left "no blink1 device found")
else do
blink1device_fptr <- newForeignPtr finalizerFree blink1device_ptr
return (Right blink1device_fptr)

blink1tool :: Word16 -> Word8 -> Word8 -> Word8 -> Word8-> (ForeignPtr Blink1Device) -> IO (Either String Int)
blink1tool fadeMillis r g b led blink1device_fptr =
withForeignPtr blink1device_fptr (\ptr -> c_blink1_fadeToRGBN ptr (fromIntegral fadeMillis) (fromIntegral r) (fromIntegral g) (fromIntegral b) (fromIntegral led)) >>= return . Right . fromIntegral
35 changes: 35 additions & 0 deletions haskell/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@

Copyright (c) ThingM, 2012-2013

'blink(1)' is a trademark of ThingM Corporation

---

LICENSE:
Creative Commons - Attribution - ShareAlike 3.0
http://creativecommons.org/licenses/by-sa/3.0/
See why we chose this license: http://www.inmojo.com/licenses/

This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/ or send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA.


This is a human-readable summary of the full license.

You are free:
- to Share - to copy, distribute and transmit the work, and
- to Remix - to adapt the work

Under the following conditions:
- Attribution - You must attribute the work in the manner specified by the author or licensor (but not in any way that suggests that they endorse you or your use of the work.)
- Share Alike - If you alter, transform, or build upon this work, you may distribute the resulting work only under the same, similar or a compatible license.

With the understanding that:
- Waiver - Any of the above conditions can be waived if you get permission from the copyright holder.
- Other Rights - In no way are any of the following rights affected by the license:
-- your fair dealing or fair use rights;
-- the author's moral rights; and
-- rights other persons may have either in the work itself or in how the work is used, such as publicity or privacy rights.

Notice - For any reuse or distribution, you must make clear to others the license terms of this work. The best way to do that is with a link to
http://creativecommons.org/licenses/by-sa/3.0/

35 changes: 35 additions & 0 deletions haskell/Main.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
module Main where

import Control.Exception
import qualified Data.ByteString.Char8 as B
import GHC.Float
import Blink1Tool
import Foreign
import Foreign.C.Types
import Foreign.C.String
import System.IO.Unsafe
import Control.Exception




setcolor :: [Int] -> ForeignPtr Blink1Device -> IO ()
setcolor (x:xs) device = do
result <- blink1tool 10 r g b 0 device
case result of
Left msg -> putStrLn msg
Right(-1) -> c_blink1_enumerate >>= \numBlink1s -> putStrLn (" error : blink1 didnt work , enumeration is "++ (show numBlink1s))
Right status -> putStrLn ("setting to "++(show r) ++ ", " ++ (show g) ++ ", " ++ (show b)) >> setcolor xs device
where
r = ((calc x sin) )
g = ((calc x cos) )
b = ((calc (x+45)) sin)
calc :: Int -> (Float -> Float) -> Word8
calc a f = fromIntegral (float2Int (f (fromIntegral a) *100))

main::IO()
main= do
device <- blink1device
case device of
Left msg -> putStrLn msg
Right device -> setcolor [1..] device
61 changes: 61 additions & 0 deletions haskell/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#Haskell Bindings

Hasnt been tested on a windows system however in theory should work

prerequisites: library should be installed to the system at default locations, this is where Haskells FFI will look

may leak handles, I create a managed pointer to handle deallocation but do not explicitly call the close function. future function would be to create the necessary finalizer that calls close before deallocating memory

included in the directory is a Main.hs which can be easily run and compiled in place by calling the included compileMain, this should be worked into cabal and this will follow shortly

Main.hs sends a series of colors to the first available device in an infite loop

## Exported functions


```
c_blink1open :: IO (Ptr Blink1Device)
--
--Scan USB for blink(1) devices.
-- @return number of devices found
--
c_blink1_enumerate :: IO (CInt)
c_blink1_close:: Ptr Blink1Device -> IO ()
-- Fade blink1 to given RGB color over specified time.
-- @param dev blink1 device to command
-- @param fadeMillis time to fade in milliseconds
-- @param r red part of RGB color
-- @param g green part of RGB color
-- @param b blue part of RGB color
--@return -1 on error, 0 on success
c_blink1_fadeToRGBN :: Ptr Blink1Device -> CUShort -> CUChar -> CUChar -> CUChar -> CUChar
```

## utility functions
```
-- returns either an error msg or a managed pointer
blink1device :: IO (Either String (ForeignPtr Blink1Device))
-- fademillis r g b lednum device
blink1tool :: Word16 -> Word8 -> Word8 -> Word8 -> Word8-> (ForeignPtr Blink1Device) -> IO (Either String Int)
```


#Use
generally call blink1device to get a managed pointer , then use it pointer to call blinktool
if you want to set up more bindings you will need to study the withForeignPtr call
see source code for blink1tool and chapter 17 of Real world Haskell

thanks all

G
33 changes: 33 additions & 0 deletions haskell/blink1haskell.cabal
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
-- Initial blink1haskell.cabal generated by cabal init. For further
-- documentation, see http://haskell.org/cabal/users-guide/

name: blink1haskell
version: 0.1.0.0
synopsis: haskell bindings for the blink1 device
description: haskell bindings for the blink1 device
license: OtherLicense
license-file: LICENSE
author: Greg Nwosu
homepage: https://github.com/gregnwosu/blink1.git
maintainer: [email protected]
-- copyright:
category: bindings for blink1 c library
build-type: Simple
-- extra-source-files:
cabal-version: >=1.10


library
-- exposed-modules:
-- other-modules:
-- other-extensions:
build-depends: base >=4.7 && <4.8
-- include-dirs:
-- includes:
-- extra-lib-dirs:
extra-libraries: blink1
default-language: Haskell2010
build-tools: hsc2hs



4 changes: 4 additions & 0 deletions haskell/compileMain
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#! /bin/bash

# script to compile a small example use of ffi through haskell, see Main.hs
hsc2hs Blink1Tool.hsc && ghc Blink1Tool.hs Main.hs -O -lblink1

0 comments on commit ab32cdf

Please sign in to comment.