A computer-readable storage medium storing a program that, when executed by a processor, causes the processor to: read values indicative of pressure within a pipe that has drilling fluid flowing therein, the drilling fluid carries pressure pulses that encode data, wherein a pressure pulse is a first pressure transition to a changed drilling fluid pressure, followed by a second pressure transition to substantially the original drilling fluid pressure; detect, in the values indicative of pressure, pressure transitions associated with the pressure pulses by causing the processor to: calculate a running average time series with each datum in the running average time series being an average of the values indicative of pressure within a predetermined window of values; create a filtered pressure time series from the values indicative of pressure; detect negative pressure transitions in the filtered pressure time series that correspond in time to the running average time series reaching a first predetermined value and the running average time series having a negative slope; and detect positive pressure transitions in the filtered pressure time series that correspond in time to the running average time series reaching a second predetermined value and the running average time series having a positive slope; and determine from an amount of time between pressure transitions at least a portion of the data encoded in the pressure pulses. read values indicative of pressure within a pipe that has drilling fluid flowing therein, the drilling fluid carries pressure pulses that encode data, wherein a pressure pulse is a first pressure transition to a changed drilling fluid pressure, followed by a second pressure transition to substantially the original drilling fluid pressure; detect, in the values indicative of pressure, pressure transitions associated with the pressure pulses by causing the processor to: calculate a running average time series with each datum in the running average time series being an average of the values indicative of pressure within a predetermined window of values; create a filtered pressure time series from the values indicative of pressure; detect negative pressure transitions in the filtered pressure time series that correspond in time to the running average time series reaching a first predetermined value and the running average time series having a negative slope; and detect positive pressure transitions in the filtered pressure time series that correspond in time to the running average time series reaching a second predetermined value and the running average time series having a positive slope; and calculate a running average time series with each datum in the running average time series being an average of the values indicative of pressure within a predetermined window of values; create a filtered pressure time series from the values indicative of pressure; detect negative pressure transitions in the filtered pressure time series that correspond in time to the running average time series reaching a first predetermined value and the running average time series having a negative slope; and detect positive pressure transitions in the filtered pressure time series that correspond in time to the running average time series reaching a second predetermined value and the running average time series having a positive slope; and determine from an amount of time between pressure transitions at least a portion of the data encoded in the pressure pulses.