diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6937a8f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+_build/
+.merlin
+*.install
+.*.swp
diff --git a/CHANGES.md b/CHANGES.md
index 1f96a68..6598f17 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,3 +1,13 @@
+v1.5.0 2022-04-07
+-----------------
+
+* Only print printable ASCII characters (#17 @copy)
+* Improve error message with odd number of characters (#35 @dialohq)
+* Raise lower bound to OCaml 4.08 (#37 @hannesm)
+* Remove bigarray-compat dependency (#37 @hannesm)
+* Remove "build" from dune dependency (#34 @CraigFE)
+* Improve documentation of `of_string` (#37 @hannesm, fixes #33 #36)
+
 v1.4.0 2019-03-28
 -----------------
 
diff --git a/README.md b/README.md
index 2a1d6f8..e2c7f71 100644
--- a/README.md
+++ b/README.md
@@ -1,16 +1,15 @@
-ocaml-hex -- a minimal library providing hexadecimal converters
----------------------------------------------------------------
+### ocaml-hex -- a minimal library providing hexadecimal converters
 
 [![Build Status](https://travis-ci.org/mirage/ocaml-hex.svg)](https://travis-ci.org/mirage/ocaml-hex)
 [![docs](https://img.shields.io/badge/doc-online-blue.svg)](http://docs.mirage.io/hex/)
 
 ```ocaml
-#require "hex";;
+# #require "hex";;
 # Hex.of_string "Hello world!";;
-- : Hex.t = "48656c6c6f20776f726c6421"
-# Hex.to_string "dead-beef";;
-- : string = "ޭ��"
+- : Hex.t = `Hex "48656c6c6f20776f726c6421"
+# Hex.to_string (`Hex "deadbeef");;
+- : string = "ޭ��"
 # Hex.hexdump (Hex.of_string "Hello world!\n")
-00000000: 4865 6c6c 6f20 776f 726c 6421 0a        Hello world!.
+00000000: 4865 6c6c 6f20 776f 726c 6421 0a         Hello world!.
 - : unit = ()
 ```
diff --git a/debian/changelog b/debian/changelog
index 3ce3f0a..2e1c57e 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+ocaml-hex (1.5.0+git20220407.2.85fe242-1) UNRELEASED; urgency=low
+
+  * New upstream snapshot.
+  * New upstream snapshot.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Thu, 08 Sep 2022 13:01:11 -0000
+
 ocaml-hex (1.4.0-1) unstable; urgency=medium
 
   * Initial release (Closes: #969045)
diff --git a/hex.opam b/hex.opam
index a0ede44..86e7ad0 100644
--- a/hex.opam
+++ b/hex.opam
@@ -1,4 +1,3 @@
-version: "1.4.0"
 opam-version: "2.0"
 maintainer: "thomas@gazagnaire.org"
 authors: ["Thomas Gazagnaire" "Trevor Summers Smith"]
@@ -7,13 +6,12 @@ homepage: "https://github.com/mirage/ocaml-hex"
 doc: "https://mirage.github.io/ocaml-hex/"
 bug-reports: "https://github.com/mirage/ocaml-hex/issues"
 depends: [
-  "ocaml" {>="4.03.0"}
-  "dune" {build & >= "1.0"}
+  "ocaml" {>="4.08.0"}
+  "dune" {>= "1.0"}
   "cstruct" {>= "1.7.0"}
-  "bigarray-compat" {>= "1.0.0"}
 ]
 build: [
-  ["dune" "subst"] {pinned}
+  ["dune" "subst"] {dev}
   ["dune" "build" "-p" name "-j" jobs]
   ["dune" "runtest" "-p" name "-j" jobs] {with-test}
 ]
@@ -30,4 +28,4 @@ description: """
 00000000: 4865 6c6c 6f20 776f 726c 6421 0a        Hello world!.
 - : unit = ()
 ```
-"""
\ No newline at end of file
+"""
diff --git a/lib/dune b/lib/dune
index aeeb800..197f446 100644
--- a/lib/dune
+++ b/lib/dune
@@ -1,4 +1,4 @@
 (library
  (name hex)
  (public_name hex)
- (libraries cstruct bigarray-compat))
+ (libraries cstruct))
diff --git a/lib/hex.ml b/lib/hex.ml
index bc260f9..8f855a1 100644
--- a/lib/hex.ml
+++ b/lib/hex.ml
@@ -15,8 +15,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  *)
 
-module Bigarray = Bigarray_compat
-
 type t = [`Hex of string]
 
 let invalid_arg fmt =
@@ -34,6 +32,9 @@ and hexa2 =
    0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\
    0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
 
+let char_is_printable chr =
+  chr >= ' ' && chr <= '~'
+
 let of_char c =
   let x = Char.code c in
   hexa.[x lsr 4], hexa.[x land 0xf]
@@ -70,10 +71,10 @@ let of_helper ~ignore (next : int -> char) len =
   done;
   `Hex (Buffer.contents buf)
 
-let of_string ?ignore s =
+let of_string ?(ignore = []) s =
   match ignore with
-    None -> of_string_fast s
-  | Some ignore -> of_helper ~ignore (fun i -> s.[i]) (String.length s)
+  | [] -> of_string_fast s
+  | ignore -> of_helper ~ignore (fun i -> s.[i]) (String.length s)
 
 let of_bytes ?ignore b =
   of_string ?ignore (Bytes.to_string b)
@@ -85,7 +86,7 @@ let to_helper ~empty_return ~create ~set (`Hex s) =
     let buf = create (n/2) in
     let rec aux i j =
       if i >= n then ()
-      else if j >= n then invalid_arg "hex conversion: invalid hex string"
+      else if j >= n then invalid_arg "Hex conversion: Hex string cannot have an odd number of characters."
       else (
         set buf (i/2) (to_char s.[i] s.[j]);
         aux (j+1) (j+2)
@@ -168,10 +169,10 @@ let hexdump_s ?(print_row_numbers=true) ?(print_chars=true) (`Hex s) =
           let pos = i + (row * hex_len) in
           let pos' = pos + 1 in
           let c = to_char (String.get s pos) (String.get s pos') in
-          let () = match c with
-            | '\t' | '\n' -> buf <= "."
-            | _ -> buf <= Printf.sprintf "%c" c
-          in ();
+          if char_is_printable c then
+            buf <= Printf.sprintf "%c" c
+          else
+            buf <= ".";
           aux (j+1) (j+2)
         end
       in
diff --git a/lib/hex.mli b/lib/hex.mli
index 43456f5..dc1050f 100644
--- a/lib/hex.mli
+++ b/lib/hex.mli
@@ -38,8 +38,13 @@ val to_char: char -> char -> char
 val of_string: ?ignore:char list -> string -> t
 (** [of_string s] is the hexadecimal representation of the binary
     string [s]. If [ignore] is set, skip the characters in the list
-    when converting. Eg [of_string ~ignore:[' '] "a f"]. The default
-    value of [ignore] is [[]]). *)
+    when converting. E.g. [of_string ~ignore:[' '] "Mirage OS"] is
+    [`Hex "4d69726167654f53"], [of_string "Mirage OS"] is
+    [`Hex "4d6972616765204f53"] (with a "20" before the "OS" ("4f53")).
+    The default value of [ignore] is [[]]).
+
+    If you have a hex string as input (i.e. "4f53"), you can use
+    [to_string (`Hex "4f53")] to decode it to a binary string ("OS"). *)
 
 val to_string: t -> string
 (** [to_string t] is the binary string [s] such that [of_string s] is
diff --git a/lib_test/dune b/lib_test/dune
index 3456463..bd1a52f 100644
--- a/lib_test/dune
+++ b/lib_test/dune
@@ -1,10 +1,3 @@
-(executables
- (names test)
- (libraries hex bigarray-compat))
-
-(alias
- (name runtest)
- (deps
-  (:< test.exe))
- (action
-  (run %{<} -runner sequential)))
+(test
+ (name test)
+ (libraries hex))
diff --git a/lib_test/test.ml b/lib_test/test.ml
index 3cebcf4..0ea2482 100644
--- a/lib_test/test.ml
+++ b/lib_test/test.ml
@@ -36,7 +36,7 @@ let test_suite test =
   done
 
 let test_cs_array () =
-  let open Bigarray_compat in
+  let open Bigarray in
   let arr = Array1.of_array char c_layout
       [|'0'; '1'; '2'; '3'; '4'; '5';
         '6'; '7'; '8'; '9'; 'a'; 'b';
@@ -61,6 +61,8 @@ let test_hexdump () =
     let s = Hex.hexdump_s hex in
     check "hexdump" s answer
   in
+  (* unprintable *)
+  test "\x00\x01\x09\x10\x1f\x80\xff" "00000000: 0001 0910 1f80 ff                        .......\n";
   (* Test out the various padding situations we need to get right *)
   (* Less than 1 row *)
   test "i am less" "00000000: 6920 616d 206c 6573 73                   i am less\n";