diff --git a/gauth/gauth.go b/gauth/gauth.go
index 619328d..3b2af0a 100644
--- a/gauth/gauth.go
+++ b/gauth/gauth.go
@@ -17,15 +17,27 @@ import (
 	"github.com/creachadair/otp/otpauth"
 )
 
-// IndexNow returns the current 30-second time slice index, and the number of
-// seconds remaining until it ends.
-func IndexNow() (int64, int) {
+// IndexNow returns the current 30-second time step, and the number of seconds
+// remaining until it ends.
+func IndexNow() (uint64, int) {
 	time := time.Now().Unix()
-	return time / 30, int(time % 30)
+	return uint64(time / 30), int(time % 30)
 }
 
 // Codes returns the previous, current, and next codes from u.
 func Codes(u *otpauth.URL) (prev, curr, next string, _ error) {
+	var ts uint64
+	if u.Period > 0 {
+		ts = otp.TimeWindow(u.Period)()
+	} else {
+		ts, _ = IndexNow()
+	}
+	return CodesAtTimeStep(u, ts)
+}
+
+// CodesAtTimeStep returns the previous, current, and next codes from u at the
+// given time step value.
+func CodesAtTimeStep(u *otpauth.URL, timeStep uint64) (prev, curr, next string, _ error) {
 	if u.Type != "totp" {
 		return "", "", "", fmt.Errorf("unsupported type: %q", u.Type)
 	} else if u.Algorithm != "" && u.Algorithm != "SHA1" {
@@ -33,18 +45,12 @@ func Codes(u *otpauth.URL) (prev, curr, next string, _ error) {
 	}
 
 	cfg := otp.Config{Digits: u.Digits}
-	var ts uint64
-	if u.Period > 0 {
-		ts = otp.TimeWindow(u.Period)()
-	} else {
-		ts = otp.TimeWindow(30)()
-	}
 	if err := cfg.ParseKey(u.RawSecret); err != nil {
 		return "", "", "", fmt.Errorf("invalid secret: %v", err)
 	}
-	prev = cfg.HOTP(ts - 1)
-	curr = cfg.HOTP(ts)
-	next = cfg.HOTP(ts + 1)
+	prev = cfg.HOTP(timeStep - 1)
+	curr = cfg.HOTP(timeStep)
+	next = cfg.HOTP(timeStep + 1)
 	return
 }
 
diff --git a/gauth/gauth_test.go b/gauth/gauth_test.go
index de1ad90..9244f1e 100644
--- a/gauth/gauth_test.go
+++ b/gauth/gauth_test.go
@@ -4,14 +4,14 @@ import (
 	"bytes"
 	"testing"
 
+	"github.com/creachadair/otp/otpauth"
 	"github.com/pcarrier/gauth/gauth"
 )
 
-/* TODO: Update this test.
 func TestCodes(t *testing.T) {
 	tests := []struct {
 		secret string
-		index  int64
+		index  uint64
 		want   string
 		fail   bool
 	}{
@@ -22,14 +22,15 @@ func TestCodes(t *testing.T) {
 		{"blargh!", 123, "", true},
 	}
 	for _, test := range tests {
-		_, got, _, err := gauth.Codes(test.secret, test.index)
+		u := &otpauth.URL{Type: "totp", RawSecret: test.secret}
+		_, got, _, err := gauth.CodesAtTimeStep(u, test.index)
 		if err != nil && !test.fail {
-			t.Errorf("Code(%q, %d): unexpected error: %v", test.secret, test.index, err)
+			t.Errorf("Codes(%q) at %d: unexpected error: %v", u, test.index, err)
 		} else if got != test.want {
-			t.Errorf("Code(%q, %d): got %q, want %q", test.secret, test.index, got, test.want)
+			t.Errorf("Codes(%q) at %d: got %q, want %q", u, test.index, got, test.want)
 		}
 	}
-} */
+}
 
 //go:generate openssl enc -aes-128-cbc -md sha256 -pass pass:x -in testdata/plaintext.csv -out testdata/encrypted.csv