Last active
August 29, 2015 14:13
-
-
Save andrevdm/04c9f5fae5cbee9701b1 to your computer and use it in GitHub Desktop.
F# "logic" parser for rigol oscilloscope CSV files, outputs hex values
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
open System | |
open System.IO | |
open System.Text | |
open System.Globalization | |
open System.Text.RegularExpressions | |
let ttlTrue = 2.3 | |
let getLines (fname:string) = seq{ | |
use stream = new StreamReader( fname ) | |
while not stream.EndOfStream do | |
yield stream.ReadLine() | |
} | |
let parseVoltage (s:string) = | |
try | |
System.Double.Parse( (s.Replace( ".", "," )), NumberStyles.Float ) | |
with | |
| e -> | |
printfn "%s - %s" s (e.ToString()) | |
0.0 | |
let filterOnClockGoingHigh (s:seq<int * int>) = seq { | |
let e = s.GetEnumerator() | |
let last = ref 0 | |
while e.MoveNext() do | |
if !last <> (snd e.Current) then | |
last := (snd e.Current) | |
if !last = 1 then | |
yield e.Current | |
} | |
//from http://fssnip.net/6A | |
let groupWhen f (input:seq<_>) = seq { | |
use en = input.GetEnumerator() | |
let running = ref true | |
// Generate a group starting with the current element. Stops generating | |
// when it founds element such that 'f en.Current' is 'true' | |
let rec group() = | |
[ yield en.Current | |
if en.MoveNext() then | |
if not (f en.Current) then yield! group() | |
else running := false ] | |
if en.MoveNext() then | |
// While there are still elements, start a new group | |
while running.Value do | |
yield group() |> Seq.ofList } | |
let toNum (g:int seq) = | |
let l = List.ofSeq g | |
(if l.Length > 0 && l.[0] = 1 then 128uy else 0uy) + | |
(if l.Length > 1 && l.[1] = 1 then 64uy else 0uy) + | |
(if l.Length > 2 && l.[2] = 1 then 32uy else 0uy) + | |
(if l.Length > 3 && l.[3] = 1 then 16uy else 0uy) + | |
(if l.Length > 4 && l.[4] = 1 then 8uy else 0uy) + | |
(if l.Length > 5 && l.[5] = 1 then 4uy else 0uy) + | |
(if l.Length > 6 && l.[6] = 1 then 2uy else 0uy) + | |
(if l.Length > 7 && l.[7] = 1 then 1uy else 0uy) | |
getLines fsi.CommandLineArgs.[1] | |
//Skip headers | |
|> Seq.skip 2 | |
//Split CSV | |
|> Seq.map (fun l -> l.Split( [|','|] )) | |
//Ignore empty lines | |
|> Seq.filter (fun f -> f.Length >= 3) | |
//Parse the voltages | |
|> Seq.map (fun f -> (parseVoltage f.[1], parseVoltage f.[2]) ) | |
//Clock from voltage to logic level | |
|> Seq.map (fun (data,clock) -> ((if data > ttlTrue then 1 else 0), (if clock > ttlTrue then 1 else 0))) | |
//Get data - clock rising edge | |
|> filterOnClockGoingHigh | |
//remove the clock data | |
|> Seq.map (fun f -> fst f) | |
//Add a count to each item | |
|> Seq.mapi (fun i v -> (i,v)) | |
//group into chunks of 8 | |
|> groupWhen (fun (i,v) -> i % 8 = 0) | |
//get only the second item | |
|> Seq.map (Seq.map snd) | |
//convert each group to a number | |
|> Seq.map (fun x -> toNum x) | |
|> Seq.iter (fun x -> printfn "%02x %c" x (if (x >= 0x20uy) && (x <= 0x7euy) then char x else ' ') ) | |
//|> Seq.iter (fun f -> printfn "%A" f) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment