Fundamentals of error-correcting codes