It's an issue with this part of the code:
if (p.y > height - r) {
p.y = height - r;
v.y = -v.y;
}
Imagine that height is 600 and r is 10. When the ball hits the bottom (p.y > (600 - 10)) it gets reset to (600-10). But the ball can hit the bottom below that: p.y can be higher than height, leading to the issue you're having. The correct code in this case would then be:
if (p.y > height - r) {
p.y = (p.y - height) + (height - r);
v.y = -v.y;
}
Being (p.y - height) what you're losing each time the ball bounces.
Hope this helps.