   }
 }
 
-// Returns false if was interrupted, otherwise returns true
-boolean dim(unsigned long duration, boolean brighten) {
-  double lnb = log(pow(256.0, 1.0 / (float) duration));
-  for (int i = 1; i < 256; i++) {
+boolean dim(long duration) {
+  boolean brighten;
+  light_state = "dimming";
+  if (duration > 0) {
+    brighten = true;
+  } else {
+    brighten = false;
+    duration = -(duration);
+  }
+  for (double i = 1; i < 256; i++) {
     if (light_state != "dimming") {
       return false;
     }
     unsigned long interval;
     if (brighten) {
       analogWrite(gate_pin, i);
-      interval = (unsigned long) round(log(((float) i + 1) / (float) i) / lnb);
+      interval = (unsigned long) round(duration * (sqrt(i / 254) - sqrt((i - 1) / 254)));
     } else {
-      int x = 256 - i;
-      analogWrite(gate_pin, x - 1);
-      interval = (unsigned long) round(log((float) x / ((float) x - 1)) / lnb);
+      double x = 256 - i;
+      analogWrite(gate_pin, (int) x - 1);
+      interval = (unsigned long) round(duration * (sqrt(x / 254) - sqrt((x - 1) / 254)));
     }
     unsigned long previousMillis = millis();
     if (i < 255) {

const int gate_pin = 5;
String light_state;

void serialEvent();
boolean dim(unsigned long, boolean);
void alarm(unsigned long);
void blink(unsigned long);

void alarm(unsigned long duration) {
  unsigned long startMillis = millis();
  unsigned long dimDuration = 2ul * duration / 3ul;
  if (dim(dimDuration, true)) {
    light_state = "alarm";
    while (millis() - startMillis < duration) {
      loop();

  pinMode(gate_pin, OUTPUT);
  analogWrite(gate_pin, 0);
  light_state = "off";
  light_brightness = 0;
  Serial.begin(9600);
}

