-- |Implements Weber–Fechner law for per weight perception. Using S0
-- of 1, k of 1. See more information:
-- http://en.wikipedia.org/wiki/Weber%E2%80%93Fechner_law
module WeberFechner (weberFechnerTable,cTable) where

import Data.List (intercalate)

humanBits :: Integer
pwmBits   :: Integer
s0        :: Integer

humanBits  = 8   -- ^Input value range
pwmBits    = 12  -- ^Output value range
s0         = 10  -- ^Threshold of stimulus below which it is not perceived

a = log(2^pwmBits-fromIntegral s0)/(2^humanBits-1)

-- |Modified Weber–Fechner algorithm which saves energy when stimulus can not be
-- perceived.
weberFechner :: Integer -> Integer
weberFechner x_i | alg == s0 = 0
                 | otherwise = alg
  where alg = round (exp (a*x)) + (s0-1)
        x = fromIntegral x_i

weberFechnerTable = map weberFechner [0..2^humanBits-1]

header = "/* Pre-calculated Weber–Fechner table generated by helpers/WeberFechner.hs */"
signature = "const uint16_t weber_fechner_table[] PROGMEM"

cTable = header ++ "\n" ++ signature ++ " = {" ++ list ++ "};"
  where list = intercalate "," $ map show weberFechnerTable

main = putStrLn cTable
