The algorithm for the OpenPostcode is actually very straightforward. It defines an origin in the NorthWest, defines the height and width of the island and then uses a 5x5 grid to define areas. Each character, from left to right, defines a further 5x5 grid inside the last. The logo here illustrates the pattern and could even be used to estimate locations; however the precise mathematics is a simple use of base25 and base5 numbering.
Helpfully, a base25 number is the square of 5. So any grid reference inside a 5x5 grid can be referenced as two numbers; 0 to 4, and 0 to 4. Lets for example go for latitude 2 and longitude 3. That's 2 and 3  or even just write it as "23". Now the benefit of using base25 comes into play. Treat this as a base5 number and convert it to a base25 number and you are left with a single character encoding both coordinates. 23 as a base5 number in ordinary decimal is just 2x5+3=13, which is D in base25. The reverse is as simple. Keep doing this with more characters and you can reference positions on a national scale to a high degree of accuracy with little calculation and compact codes. (OPC Version 3, 17th April, 2012)
Conversion from Coordinates to OpenPostcode (Version 4)
e.g. Spire of Dublin 53.349795, 6.260254 (using coordinates as quoted in Wikipedia, Google imagery may vary from the exact location).
 First compare the location to the origin of the island as defined by the parameters: West 10.75, North 55.5.
 55.553.349795 = 2.150205
 10.756.260254 = 4.489746
 Then scale to percentage of the boundaries of the island by the parameters: wide=5.4, high=4.2.
 2.150205/4.2 = 0.511953571
 4.489746/5.4 = 0.831434444
 The highest scale possible is defined by the number of possible characters and number of code digits:
 "6789B5NPQC4MXRD3LWTF2KJHG" and 8.
 "6789B5NPQC4MXRD3LWTF2KJHG" gives 25 characters. The squareroot of 25 is 5 (allowing a base5 encoding of longitude and latitude in a single character). The maximum scale is therefore 5^8 digits = 390625.
 int(0.511953571*390625) = 199981
 int(0.831434444*390625) = 324779
 Convert to base5. While many languages have functions for conversion, even where no function is preprogrammed it is relatively trivial to convert from one base to base. In a spreadsheet conversion for example "=MOD(INT(Num/Base^7),Base) &MOD(INT(Num/Base^6),Base) &MOD(INT(Num/Base^5),Base) &MOD(INT(Num/Base^4),Base) &MOD(INT(Num/Base^3),Base) &MOD(INT(Num/Base^2),Base) &MOD(INT(Num/Base),Base) &MOD(Num,Base)".
 base10to5(199981) = 22344411
 base10to5(324779) = 40343104
 Digit by digit, calculate a base25 combined character from the latitude and longitude. In maths, each digit is easily isolated as: int((number mod base^position)/base^(position1)).
 2*5+4 = 14; 14 in base 25 is "E", or read from the approved alphabet (position 14+1) = "D".
 2*5+0 = 10; = "4"
 3*5+3 = 18; = "T"
 4*5+4 = 24; = "G"
 4*5+3 = 23; = "H"
 4*5+1 = 21; = "K"
 1*5+0 = 5; = "5"
 1*5+4 = 9; = "C"
 Thus the code: D4TGHK5C
 Or,
 base10to25(base25to10(22344411)*5 + base25to10(40343104)) = "EAIONL59".
 This is in a base 25 character set "0...9" and "A...N"; which equates to "D4TGHK5C" in the "6789B5NPQC4MXRD3LWTF2KJHG" character set, swapping character for character.
 Note, for managers of large databases, the integer created just before final conversion to Base25, here 88076153884, is the most efficient way to store the data.
Put simply, from coordinates to OpenPostcode:
 base10to25(base25to10(base10to5(int((55.553.349795)/4.2*390625))))*5 + base10to25(base25to10(int((10.756.260254)/5.4*390625))))) = "EAIONL59"
 Which makes "D4TGHK5C"  swapping the base 25 "0...9, A...N" character set for "6789B5NPQC4MXRD3LWTF2KJHG".

Calculation of Checksum
 For each character, multiply its number equivalent by its position (left to right); calculate the total; add the integer of the parameters west*northwide*high (which amounts to zero in the Irish calculation and so can be ignored); and calculate the total modulus (or remainder after dividing by) the number of available checksum characters ("0123456789ACDEFGHJKLMNPQRTUVWXY" = 31) thus:
 (14*1 + 10*2 + 18*3 + 24*4 + 23*5 + 21*6 + 5*7 + 9*8) mod 31 = 5
 Reading from position 5+1, the checksum character is "5".
 Thus the final 8digit code of D4TGHK5C/5.
Put simply, to calculate the checksum for the "EAIONL59" base 25 code above:
 (base25to10("E")*1 +base25to10("A")*2 +base25to10("I")*3 +base25to10("O")*4 +base25to10("N")*5 +base25to10(L)*6 +base25to10(5)*7 +base25to10(9)) mod 31 = 5
 Which equates to a checksum "5" from its character set. Thus the final 8digit code of D4TGHK5C/5.

Conversion from OpenPostcode to Coordinates
 Character by character before the dash, "D4TGHK5C", translate from the base25 character to its numerical equivalent.
 "K" = position 15 amongst positions 0 to 24. Thus the numerical equivalent of "D" = 14, and then "4" = 10, "T" = 18, "G" = 24, "H" = 23, "K" = 21, "5" = 5, "C" = 9.
 Then convert to two base5 numbers, digit by digit, latitude and longitude.
 int(14/5) = 2, 14 mod 5 = 4
 int(10/5) = 2, 10 mod 5 = 0
 int(18/5) = 3, 18 mod 5 = 3
 int(24/5) = 4, 24 mod 5 = 4
 int(23/5) = 4, 23 mod 5 = 4
 int(21/5) = 4, 21 mod 5 = 4
 int(5/5) = 1, 5 mod 5 = 0
 int(9/5) = 1, 9 mod 5 = 4
 Thus 22344411_{5}, 40343104_{5}
 Or,
 Swap the character set "6789B5NPQC4MXRD3LWTF2KJHG" for regular base 25 "0...9, A...N", which makes "EAIONL59" from "D4TGHK5C".
 Then base10to5(base25to10("EAIONL59"))="2420334443411014"
 Taking alternating characters x="22344411", y="40343104"
 The convert both to ordinary base10:
 base10(22344411_{5}) = 199981
 base10(40343104_{5}) = 324779
 Centre the point in its square:
 199981+.5=199981.5
 324779+.5=324779.5
 Return to a percentage of the maximum extent of the grid (5^8 = 390625).
 199981.5/390625 = 0.51195264
 324779.5/390625 = 0.83143552
 Scale up to the extent of the island boundaries (wide=5.4, high=4.2).
 0.51195264*4.2 = 2.150201088
 0.83143552*5.4 = 4.489751808
 Set on the origin of the island grid (as defined by West 10.75, North 55.5).
 Finally, to verify the checksum; recalculate and compare.
Put simply, from OpenPostcode to coordinates:
 For "D4TGHK5C", swap the character set "6789B5NPQC4MXRD3LWTF2KJHG" for regular base 25 "0...9, A...N".
 base10to5(base25to10("EAIONL59"))="2420334443411014"
 Taking alternating characters:
 55.5(base5to10("22344411")+.5)/390625*4.2 = 53.349798912
 (base5to10("40343104")+.5)/390625*5.4 10.75 = 6.260248192

See also:
