digitalWrite(dataPin, !!(val & (1 << i)));
Nope, because, for example, 5 & (1 << 2) is 4, not 1. Really, I should have used (val >> i) & 1 instead.